投稿日:2021年1月23日
CreateReactAppにはCSSのセレクタ名の解決を優秀に行うCSSモジュールという機能が存在します。この記事ではCSSモジュールについて解説しています。
CSSではその性質上セレクタ名を決めることが長年の課題になってきました。
FLOCSSやBEMなどのCSSの設計を勉強したことがある方は、その以上に長いセレクタ名を管理する精神的ストレスを知っていると思います。
JavaScriptのWebフレームワークであるCreateReactAppにはこの課題を解決するCSSモジュールというものが存在します。
この記事の環境は以下の通りです。
CreateReactAppフレームワークで作成したReactアプリケーションにはデフォルトで便利なCSSモジュール機能がついています。
この機能を使用することで、BEMやFLOCSSなどの設計を駆使して面倒で長ったらしいCSSのクラス名を決める必要がなくなります。
まず以下のようなcssファイルがあるとします。
(create-react-appコマンドで生成されるサンプルのcssです)
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
このCSSファイルを読み込ませる時、通常なら以下の様にします。
(これもコマンドで作成されるサンプルファイルです)
import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
ではこれをCSSモジュールを使う形に変更してみましょう。
CSSモジュール機能を使うにはまずCSSファイルの拡張子を.cssから.module.cssに変更します。
今回の場合はApp.cssをApp.module.cssに変更します。
次にReactのJavaScriptコードを変更します。
まず呼び出す側のスクリプトのCSSのimport文をデフォルトexportのimportに変更します。次に、対象のクラス名の参照をimportした変数からドット(.)またはブラケット([])で呼び出します。
ハイフンのついたクラス名はドット.でアクセスできない為ブラケット[]で参照しましょう。
import React from "react";
import logo from "./logo.svg";
import style from "./App.module.css"; // import文を変更
function App() {
return (
<div className={style.App}>
<header className={style["App-header"]}>
<img src={logo} className={style["App-logo"]} alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className={style["App-link"]}
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
するとビルド時にcss、html双方のセレクタが{コンポーネント名}_{モジュールのクラス名}__{ランダム値}に書き直されます。
[...]
<div class="App_App__16ZpL"></div>
[...]
[...]
.App_App__16ZpL {
text-align: center;
}
[...]
これによってビルドされた後のコードでそれが重複することは決してないため、CSSの管理が非常に楽になります。
上の例の通り、CSSモジュール機能ではハイフン(-)のついたクラス名はドット(.)で参照できません。
.module.cssファイルのセレクタ名にはハイフンを使わず、できるだけ短い名前をつけるのが良いでしょう。
もしつけるとしてもアンダーバー(_)を使う様にしましょう。