CSS のコンポーネント化ができる CSS Modules というものを知りました。使うと CSS のクラス名をファイルごとに変換してくれます。変換後のクラス名を JavaScript で DOM に割り当てるようです。
React と組み合わせて使ってみました。
インストール
CSS Modules はいくつか使う方法があるみたいです。 Browserify のプラグインもあって、今回はそれを使って見ます。Browserify や Babel プラグイン、 React もインストールしておきます。
$ npm install -g browserify
$ npm install -D babelify css-modulesify
$ npm install -S react react-dom
CSS を JavaScript から読み込む
例として単純なクラスを定義してみます。
/* a.css */
.red {
color: red;
}
この red
というクラスを使うコードが以下です。
// a.js
import React from 'react';
import ReactDOM from 'react-dom';
import styles from './a.css';
class App extends React.Component {
render() {
return <div className={styles.red}>Hello, World!</div>;
}
}
ReactDOM.render(<App />, document.querySelector('#app'));
a.css
を import
しているのがポイントです。 styles.red
には変換されたクラス名が入っています。 Browserify の変換時にプラグインのオプションを指定します。
$ browserify -o dist/script.js -p [ css-modulesify -o dist/style.css ] -t babelify a.js
css-modulesify
が dist/style.css
にクラス名が変換された CSS を吐き出します。 HTML から dist/script.js
と dist/style.css
を読みこめば、 Hello, World!
という文字が赤く表示されます。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="dist/style.css">
</head>
<body>
<div id="app"></div>
<script src="dist/script.js"></script>
</body>
</html>
同じクラス名を使う
これだけだとありがたみがわかりにくいので、同じクラス名を使ってみます。
// a.js
import React from 'react';
import ReactDOM from 'react-dom';
import { B } from './b';
import styles from './a.css';
class App extends React.Component {
render() {
return <div className={styles.red}>Hello, <B>World!</B></div>;
}
}
ReactDOM.render(<App />, document.querySelector('#app'));
<B>
というコンポーネントを使っています。その中で red
というクラスを使ってみます。
// b.js
import React from 'react';
import styles from './b.css';
export class B extends React.Component {
render() {
return <span className={styles.red}>{this.props.children}</span>;
}
}
/* b.css */
.red {
color: white;
background-color: red;
}
これをコンパイルすると、 <App>
と <B>
でそれぞれ別のスタイルが適用されます。
まとめ
これまで BEM や SMACSS なんかで CSS のコンポーネント化を頑張っていたと思います。
CSS Modules は JavaScript 側からのアプローチをしていて命名を頑張る必要がなくて、開発者からすると簡単に使えそうです。 Browserify を使っていればビルドのフローに組み込むのもプラグインを指定するだけでできます。
逆にデザイナーと開発者で分業していたりすると使うのは少し難しそうです。