React 速習チュートリアル

React CSS Modules

1. CSS Modulesとは?

CSS Modules を使用すると、特定のコンポーネントに対してのみ有効な、ローカルにスコープされたCSSを記述することができます。

これにより、CSSクラス名の衝突(コンフリクト)を防止し、スタイルのメンテナンス性を大幅に向上させることが可能です。

       注意: CSS ModulesはReactのコアライブラリの一部ではありませんが、多くのReactビルドツール(Create React AppやViteなど)で標準サポートされています。

CSS Modulesを使用する場合、ファイル名を .module.css という拡張子にする必要があります。利用する際は、そのファイルをReactファイルにインポートして使用します。

2. CSSモジュールの作成

ボタンのスタイルを定義する Button.module.css という名前のCSSモジュールを作成してみましょう。

2.1 スタイル定義の例

Button.module.css というファイルを作成し、以下のスタイルを記述します。

Button.module.css

.mybutton {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

3. CSSモジュールの使用方法

作成したCSSモジュールをコンポーネントにインポートして適用します。

3.1 実装例

CSSモジュールを使用する Button コンポーネントを作成します。

import styles from './Button.module.css';

function App() {
  return (
    <div>
      {/* stylesオブジェクトを介してクラスにアクセス */}
      <button className={styles.mybutton}>
        マイ・ボタン
      </button>
    </div>
  );
}

3.2 コードの解説

  1. CSSモジュールから styles オブジェクトをインポートします。
  2. styles.mybutton を使用して mybutton クラスにアクセスします。
  3. ブラウザでレンダリングされる際、ボタンの実際のクラス名は一意の文字列(例:_mybutton_q1obu_1)に変換されるため、他のファイルとの衝突が起こりません。

4. 複数のクラスの適用

一つの要素に複数のクラスを適用することも可能です。

4.1 CSSの定義

Button.module.css にスタイルを追加します。

Button.module.css

.mybutton {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.primary {
  background-color: #007bff;
  color: white;
}

.secondary {
  background-color: #6c757d;
  color: white;
}

4.2 コンポーネントでの適用例

テンプレートリテラルを使用して、複数のクラスを結合します。

import styles from './Button.module.css';

function App() {
  return (
    <div>
      <button className={`${styles.mybutton} ${styles.primary}`}>
        プライマリ・ボタン
      </button>
      <button className={`${styles.mybutton} ${styles.secondary}`}>
        セカンダリ・ボタン
      </button>
    </div>
  );
}

5. クラスの継承 (composes)

CSS Modulesでは、composes キーワードを使用してクラスを組み合わせることができます。これは、あるクラスが別のクラスのスタイルを継承することを意味します。

先ほどの例では、primarysecondary の両方が mybutton のスタイルに依存していました。これを composes を使って整理してみましょう。

5.1 composesの使用例

Button.module.css

.mybutton {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.primary {
  composes: mybutton;
  background-color: #007bff;
  color: white;
}

.secondary {
  composes: mybutton;
  background-color: #6c757d;
  color: white;
}

このように定義すると、コンポーネント側では primarysecondary を指定するだけで、自動的に mybutton のスタイルも適用されます。

import styles from './Button.module.css';

function App() {
  return (
    <div>
      <button className={styles.primary}>
        プライマリ・ボタン
      </button>
      <button className={styles.secondary}>
        セカンダリ・ボタン
      </button>
    </div>
  );
}

6. グローバルクラス (Global Classes)

通常、CSSモジュール内のクラスはインポートしたコンポーネント内でのみ有効です。これは、クラス名にファイル名のハッシュ値などが付加されるためです。

しかし、特定のクラスをグローバル(全体)で利用可能にし、他のコンポーネントからも参照したい場合があります。その場合は :global 構文を使用します。

6.1 実装例

BlueHeader.module.css というファイルでグローバルクラス .myheader を定義します。

BlueHeader.module.css

:global(.myheader) {
  padding: 10px 20px;
  font-size: 50px;
  color: white;
  background-color: dodgerblue;
}

:global でラップされたクラスは、_myheader_q1obu_1 のようなユニークな名前には変換されず、そのまま .myheader として扱われます。

6.2 コンポーネントでの使用

インポートした styles オブジェクトを介さず、通常の文字列としてクラス名を指定できます。

import styles from './BlueHeader.module.css';

function App() {
  return (
    <div>
      {/* styles.myheader ではなく文字列で指定 */}
      <h1 className="myheader">
        マイ・ヘッダー
      </h1>
    </div>
  );
}

7. グローバルクラスとローカルクラスの併用

一つのCSSモジュール内で、グローバルクラスとローカルクラスを混在させることも可能です。

7.1 実装例

MyStyles.module.css

:global(.myheader) {
  padding: 10px 20px;
  font-size: 50px;
  color: white;
  background-color: dodgerblue;
}

.myparagraph {
  font-size: 20px;
  color: white;
  background-color: purple;
}

7.2 コンポーネントでの使用

import styles from './MyStyles.module.css';

function App() {
  return (
    <div>
      {/* グローバルクラスは文字列で指定 */}
      <h1 className="myheader">
        マイ・ヘッダー
      </h1>
      {/* ローカルクラスはstylesオブジェクトから指定 */}
      <p className={styles.myparagraph}>
        マイ・パラグラフ
      </p>
    </div>
  );
}