はじめに
最近いろいろなところでのReactの活用事例が増えてきています。Facebook、Instagramはもちろん、TwitterのモバイルviewもReactが使われています。
SPAを構築していくときに、必要になるのがアニメーションだと思っています。ユーザに対してしっかりとしたフィードバックがないと、何が起こったかがわかりづらいですよね。そこで、必要になるのがCSSのkeyframes propertyです。
そもそも、ReactでのCSSはいろいろ手法があると思います。世界中の素晴らしいエンジニアたちはいろいろなNPMモジュールを作成しています。CSS ModulesやRadium、keyframesのためのReact Componentを作っていたりします。
しかし、僕自身あまりCSSをシュッと構築できないので、CSSのファイルを用意してなんとかするタイプのものはあまりうまく使えないのです。しかも、ReactにはもともとInline Styleが用意されているので、それを存分に使った方が、いいのではないかと考えました。(ただし、CSSを綺麗に書ける方はCSS使った方が良さそうです。)
方法
単純です。CSSStyleSheet interfaceというWebAPIを利用します。
方針としては、<style>
タグのDOMを作って、<head>
要素の中に作ったDOMを追加します。そうすると追加した<style>
タグのsheet
というプロパティにCSSStyleSheetのインスタンスが入ります。そしてCSSStyleSheet#insertRule(rule, index)
というメソッドを使って、keyframes propertyを定義してあげるという方法です。
例えば下記のような関数を定義してあげます。
const injectStyle = (style) => {
const styleElement = document.createElement('style');
let styleSheet = null;
document.head.appendChild(styleElement);
styleSheet = styleElement.sheet;
styleSheet.insertRule(style, styleSheet.cssRules.length);
};
export default injectStyle;
そして、以下のようなComponentを作成します。
import React from 'react';
import injectStyle from './path/to/injectStyle';
export default class SampleComponent extends React.Component {
constructor(props) {
super(props);
const keyframesStyle = `
@-webkit-keyframes pulse {
0% { background-color: #fecd6d; }
25% { background-color: #ef7b88; }
50% { background-color: #acdacf; }
75% { background-color: #87c3db; }
100% { background-color: #fecd6d; }
}
`;
injectStyle(keyframesStyle);
this.state.style = {
container: {
WebkitAnimation: 'pulse 10s linear infinite',
},
title: {
fontSize: '2rem',
},
}
}
render() {
const { style } = this.state;
return (
<div style={style.container}>
<h3 style={style.title}>Hello world using React!</h3>
</div>
);
}
}
上記のようにすることで、Inline Styleを利用しながら、あまり方法がなかったkeyframes propertyを定義してアニメーションすることができます。
まとめ
試しに動かす分には十分な方法だと思いますが、おそらく大きなプロジェクトで使う場合には採用しない方がいいかもしれない方法です。そもそもCSS in JSという方法はあまり利用されていないのかもしれません。僕が知る限り、ほとんどのReactのプロジェクトではスタイルはCSSで定義して、CSS Modulesで適用することがほとんどだと思います。
僕が知っているCSS in JSを採用している大きなプロジェクトは、Material-UIというGoogleのマテリアルデザインをReactで実装したプロジェクトくらいです。
ただ、自分の中では結構Inline Styleが気に入っているので、できる方法がないか探してみた次第です。
このエントリのサンプルコードのGist https://gist.github.com/yamadayuki/f1ea9ccacad7f1c140457b5877fb54cc