LoginSignup
0
0

状況

現在の問題点

Vite + React という構成で開発を行っており、以下のような問題に直面しました。

例: Example.tsx
// 下記の CSS で Example コンポーネントのスタイルを定義している
import "./style.css"

const Example = () => {
  return (
    {/* text という名前のクラスが他の CSS で定義されていると干渉してしまう */}
    <p className="text">これは例です</p>
  );
}

問題の具体例

異なるコンポーネントで同じクラス名を使用すると意図しないスタイルの干渉が発生します。
例えば text クラスが異なるスタイルを持つ複数のコンポーネントで定義されている場合、どのようにスタイルが適用されるかが予測困難になります。

今回はこの問題を解決するために CSS Modules を導入し、各コンポーネントのスタイルを独立させることにしました。

CSS Modules の概要とメリット

CSS Modules は各コンポーネントごとにスコープされた CSS を提供する手法です。
これによりクラス名の衝突を防いでコンポーネントごとのスタイルを独立させることができます。

CSS Modules の導入

Vite + React 環境の設定

まず Vite + React プロジェクトをセットアップします。

# Vite プロジェクトの作成
npm create vite@latest my-project --template react

# プロジェクトディレクトリに移動
cd my-project

# 依存関係のインストール
npm install

CSS Modules の設定

Vite では CSS Modules がデフォルトでサポートされています。そのため CSS ファイルの拡張子を .module.css とするだけで利用可能です (.module.scss でも可)。

しかし example-text のようにハイフン付きでスタイルを書いている場合、React の className に適用しようとするとエラーを吐きます。

なのでハイフン付きクラスをキャメルケースでも呼び出せるように設定しておきます。

vite.config.ts
export default defineConfig({
  plugins: [react()],
  css: {
    modules: {
      localsConvention: 'dashes',
    }
  }
});

これで example-text クラスを定義していた場合、React からは exampleText として呼び出せます。

実装例

CSS Modules を使用した具体例です。

例: Example.tsx
// モジュールオブジェクトを受け取る
import styles from "./style.module.css"

const Example = () => {
  return (
    {/* style.module.css で定義した text クラスを使う */}
    <p className={styles.text}>これは例です</p>
  );
}

型宣言ファイルの作成

TypeScript を使用している場合、CSS Modules の型宣言が必要です。
プロジェクトのルートディレクトリまたは src フォルダ配下などに vite-env.d.ts ファイルを作成して以下の内容を追加します。

vite-env.d.ts
/// <reference types="vite/client" />

declare module '*.module.css' {
  const classes: { [key: string]: string };
  export default classes;
}

さらに tsconfig.json を編集して型宣言ファイルを含めます。

tsconfig.json
{
  "compilerOptions": {
    "...省略..."
  },
  "include": ["src/**/*", "vite-env.d.ts"]
}

実装結果の確認

実際にビルドされた CSS の確認

CSS Modules を使用してビルドした結果、以下のようにクラス名が一意に変更されます。

._text_jaca6_10 { color: red; }
._text_svqqv_15 { font-size: 32px; }

これにより異なるコンポーネントで定義された同名のクラス (例だと text) が干渉することなく使用できます。

CSS Modules に関する設定オプション

Vite では CSS Modules に関する詳細な設定オプションが提供されています。
以下のように vite.config.ts にオプションを追加することでカスタム設定が可能です。

vite.config.ts
export default {
  css: {
    modules: {
      // CSS をローカルにスコープするデフォルトの挙動
      scopeBehaviour: 'local',
      // 例外としてグローバルスコープにしたいパス
      globalModulePaths: [/global/],
      // クラス名の生成ルールを設定
      generateScopedName: '[name]__[local]___[hash:base64:5]', 
    }
  }
}

この他にもオプションがあるため、詳しくは次のリンクを参照して下さい。

まとめ

CSS Modules を導入することでクラス名の衝突を防ぎ、各コンポーネントのスタイルを独立させることができました。
それによりスタイルの管理が容易となり、予期せぬスタイルの干渉も解消されてストレスが減りました!

この記事が役に立ったら 🩷 を頂けると嬉しいです!

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0