JavaScript でコンポーネントを作ると CSS のクラス名が被らないようにするのが意外に面倒です。対策は命名規則で対応したり CSS を JavaScript からインポートするなど、色々あります。そのなかで JavaScript の中に CSS を書く CSS in JS など言われるアプローチを採用している CSJS を試してみます。

インストール

csjs というパッケージをインストールすれば使えます。例として React コンポーネントを使うので Browserify と Babel と関連プラグインもインストールしておきます。

$ npm install -D csjs
$ npm install -g browserify babelify babel-preset-es2015 csjs-extractify
$ npm install -S react react-dom

React で試す

簡単にボタンが1つだけ表示される画面を作ってみます。

// a.js

import React from 'react';
import { render } from 'react-dom';

import styles from './a.csjs';

export class App extends React.Component {
    render() {
        return (
            <div>
                <button className={styles.btn}>Button</button>
            </div>
        );
    }
}

render(<App />, document.querySelector('#app'));

基本的な React のコンポーネントです。 import stlyes from './a.csjs'a.csjs.js からクラス名をインポートしています。

つぎに a.csjs.js の中に Template String で CSS を書きます。

// a.csjs.js

import csjs from 'csjs';

module.exports = csjs`
    .btn {
        background-color: #EEE;
        border: 1px solid #888;
        border-radius: 3px;
    }
`;

Browserify でコンパイルし、適当な HTML を用意して確認すると CSS が適用されているのがわかります。

$ browserify -t [ babelify --presets es2015 --presets react ] \
  -p [ csjs-extractify -o styles.css ] \
  -o bundle.js a.js
<!DOCTYPE html>
<meta charset="utf-8">
<div id="app"></div>
<script src="bundle.js"></script>

Browserify で csjs-extractify プラグインを使って .csjs ファイルから styles.css を生成します。

気になったところとか

csjs`...`という形式で JavaScript の中に CSS をかけました。しかしcsjs-extractifyで CSSファイルを書き出すためにはmodule.exports = ... の形式にする必要があったので使いドコロが難しい気もします。もう少しカジュアルに CSS in JS できると使いやすそうです。

babel-plugin-csjs-postcss パッケージをインストールすれば postcss を使った変換もできるみたいなのでおしいと感じました。