CSS Modules
CSS ファイルのクラス名を自動的にスコープ化し、名前衝突を防止する CSS のモジュール化手法
CSSフロントエンド
CSS Modules とは
CSS Modules は、CSS ファイルのクラス名をビルド時にユニークな名前に変換し、コンポーネントごとにスコープされたスタイルを実現する手法である。.module.css の拡張子で CSS ファイルを作成し、JavaScript からクラス名をオブジェクトとしてインポートする。Next.js のデフォルトの CSS スコーピング手法だ。
基本的な使い方
/* Button.module.css */
.button {
background: #007bff;
color: white;
padding: 8px 16px;
border-radius: 4px;
}
.primary {
background: #007bff;
}
.danger {
background: #dc3545;
}
// Button.tsx
import styles from './Button.module.css';
function Button({ variant = 'primary', children }) {
return (
<button className={`${styles.button} ${styles[variant]}`}>
{children}
</button>
);
}
// 出力: <button class="Button_button_a1b2c Button_primary_d3e4f">
ビルド時にクラス名が Button_button_a1b2c のようにユニークな名前に変換されるため、他のコンポーネントの .button クラスと衝突しない。
CSS-in-JS / Tailwind との比較
| 手法 | スコーピング | ランタイムコスト | 型安全 | 学習コスト |
|---|---|---|---|---|
| CSS Modules | ビルド時 | なし | 限定的 | 低い |
| CSS-in-JS (styled-components) | ランタイム | あり | あり | 中程度 |
| Tailwind CSS | ユーティリティクラス | なし | なし | 中程度 |
| vanilla-extract | ビルド時 | なし | あり | 中程度 |
CSS Modules はランタイムコストがゼロで、既存の CSS の知識がそのまま使える。React Server Components とも互換性がある。
Next.js での CSS Modules
Next.js は CSS Modules をゼロコンフィグでサポートする。
// app/page.tsx
import styles from './page.module.css';
export default function Home() {
return <main className={styles.main}>Hello</main>;
}
TypeScript での型定義
CSS Modules のクラス名に型を付けるには、typed-css-modules や typescript-plugin-css-modules を使う。
// Button.module.css.d.ts (自動生成)
declare const styles: {
readonly button: string;
readonly primary: string;
readonly danger: string;
};
export default styles;
composes (コンポジション)
/* base.module.css */
.text { font-size: 14px; line-height: 1.5; }
/* Button.module.css */
.button {
composes: text from './base.module.css';
background: #007bff;
}
composes で他の CSS Modules のクラスを合成できる。継承ではなくコンポジションでスタイルを再利用する。
CSS Modules の限界
- 動的なスタイル (props に応じた変更) は CSS 変数で対応する必要がある
- グローバルスタイル (リセット CSS、フォント) は
:global()で記述する - クラス名の結合が冗長になりがち (
clsxライブラリで改善)
実務での活用方法は関連書籍にも詳しい。