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-modulestypescript-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 ライブラリで改善)

実務での活用方法は関連書籍にも詳しい。

関連用語