ReactでCSS Modulesを活用したスケーラブルなアプリ設計術

Reactを使ったフロントエンド開発では、コンポーネント設計とスタイリングが密接に関わり合います。その中で、CSS Modulesは効率的でスケーラブルなスタイル管理を実現するための強力なツールです。しかし、CSS Modulesを単に利用するだけでは、大規模なアプリケーションのスケーラビリティやメンテナンス性を十分に発揮できない場合があります。本記事では、CSS Modulesの基本的な使い方からスケーラブルなデザイン戦略まで、Reactアプリケーションに特化した実践的なアプローチを詳しく解説します。CSS Modulesを駆使し、クリーンで再利用可能なスタイルを実現する方法を学びましょう。

目次
  1. CSS Modulesとは?
    1. Reactでの基本的な利用方法
    2. CSS Modulesが生成するクラス名
  2. CSS Modulesの利点
    1. 1. クラス名のスコープ管理
    2. 2. 保守性と再利用性の向上
    3. 3. パフォーマンスの向上
    4. 4. 型安全性のサポート
    5. 5. 開発者体験の向上
  3. スケーラブルなデザインの重要性
    1. 1. プロジェクト規模の拡大による課題
    2. 2. スケーラブルな設計がもたらすメリット
    3. 3. CSS Modulesとスケーラブル設計の関係
    4. 4. スケーラビリティが重要なシナリオ
  4. CSS Modulesを活用したフォルダ構成例
    1. 1. 基本的なフォルダ構成
    2. 2. 機能単位での構成
    3. 3. テーマ対応のフォルダ構成
    4. 4. プロジェクト規模に応じた構成の選択
  5. コンポーネント単位のスタイリング戦略
    1. 1. コンポーネントとCSS Modulesの一対一の関係
    2. 2. 状態に応じたスタイルの適用
    3. 3. 子コンポーネントとのスタイル分離
    4. 4. ユーティリティクラスの併用
    5. 5. コンポーネント単位スタイリングのメリット
  6. グローバルスタイルとのバランス
    1. 1. グローバルスタイルが必要な場面
    2. 2. グローバルスタイルの管理方法
    3. 3. CSS Modulesとの使い分け
    4. 4. 実践例: グローバルスタイルとCSS Modulesの共存
    5. 5. 注意点
  7. 応用例: テーマ切り替えの実装
    1. 1. テーマ切り替えの概要
    2. 2. テーマ用のCSSファイルの準備
    3. 3. Reactでテーマ状態を管理
    4. 4. テーマ切り替えの実装ポイント
    5. 5. 実践例のデモ
    6. 6. 拡張可能な設計
    7. 7. 注意点
  8. よくある課題とその解決方法
    1. 1. グローバルスタイルの利用とCSS Modulesの混在
    2. 2. 状態に応じた動的なクラス名の適用
    3. 3. 長いクラス名の可読性
    4. 4. 大規模プロジェクトでのスタイルの再利用
    5. 5. CSS Modulesの適用範囲外のスタイル制御
    6. 6. パフォーマンスの最適化
    7. 7. 型安全性の確保
  9. 演習問題: CSS Modulesで作る小さなプロジェクト
    1. 目標
    2. 1. プロジェクト構成
    3. 2. グローバルスタイルの設定
    4. 3. ToDoItemコンポーネント
    5. 4. ToDoListコンポーネント
    6. 5. Appコンポーネント
    7. 6. 演習のポイント
    8. 7. 拡張タスク
  10. まとめ

CSS Modulesとは?

CSS Modulesは、CSSファイルをモジュールとして扱い、各スタイルを自動的にユニークなクラス名に変換する仕組みです。これにより、クラス名の衝突を防ぎ、スタイルのスコープをコンポーネントに限定することができます。

Reactでの基本的な利用方法

ReactでCSS Modulesを利用する際は、通常のCSSファイルに.module.cssという拡張子を付けて管理します。以下に基本的な使用例を示します。

// Button.module.css
.button {
  background-color: blue;
  color: white;
  padding: 10px;
  border-radius: 5px;
}
// Button.js
import React from 'react';
import styles from './Button.module.css';

const Button = () => {
  return <button className={styles.button}>Click Me</button>;
};

export default Button;

この例では、styles.buttonを使用することで、コンポーネント内部にスコープされたユニークなクラス名が適用されます。

CSS Modulesが生成するクラス名

CSS Modulesは、[filename]__[classname]__[hash]という形式でクラス名を生成します。例えば、上記の例では、.buttonクラスが自動的にButton_button__abc123のような名前に変換され、他のコンポーネントとの競合を防ぎます。

CSS Modulesは、簡潔で明確な方法でスタイリングを管理し、Reactアプリケーションをよりモジュール化された形で構築するための理想的な選択肢です。

CSS Modulesの利点

CSS Modulesを活用すると、スタイル管理の課題を解決し、Reactアプリケーションの開発効率を向上させることができます。以下に、CSS Modulesの主な利点を詳しく解説します。

1. クラス名のスコープ管理

CSS Modulesでは、クラス名が自動的にユニークな名前に変換されるため、クラス名の衝突を防ぐことができます。これにより、他のコンポーネントや外部ライブラリとの競合を心配することなくスタイリングが可能です。

例: クラス名の競合回避

以下の2つのCSSファイルがあっても問題は発生しません。

/* Header.module.css */
.title {
  color: blue;
}

/* Footer.module.css */
.title {
  color: green;
}

それぞれがユニークな名前(例: Header_title__abc123Footer_title__xyz456)として処理されます。

2. 保守性と再利用性の向上

CSS Modulesは、スタイルをコンポーネントごとに分離するため、モジュール化された設計が可能です。この構造により、コードの保守性が向上し、特定のコンポーネントを他のプロジェクトでも再利用しやすくなります。

3. パフォーマンスの向上

CSS Modulesは、必要なスタイルだけをコンポーネントごとに読み込むため、CSS全体のサイズを小さく抑えることができます。また、コンパイルされたCSSファイルは、ブラウザのキャッシュ効率も向上させます。

4. 型安全性のサポート

TypeScriptを利用する場合、CSS Modules用の型定義を追加することで、スタイルに型安全性を導入できます。これにより、予期しないクラス名のエラーを防ぐことが可能です。

例: TypeScriptでの型定義

以下の型定義ファイルを追加します。

// Button.module.css.d.ts
declare const styles: {
  button: string;
};
export default styles;

TypeScriptのサポートにより、styles.buttonが存在しない場合にエラーが発生します。

5. 開発者体験の向上

CSS Modulesは、直感的でシンプルな構文を提供するため、学習コストが低く、開発者がすぐに利用できます。また、React開発に適した構造のため、開発の流れを中断せずにスタイリングを行えます。

CSS Modulesは、Reactアプリケーションにおいて効率的なスタイリングを実現するための強力なツールであり、その利点を活用することで、開発者体験とアプリケーションの品質を大きく向上させることができます。

スケーラブルなデザインの重要性

Reactアプリケーションは、プロジェクトの規模や機能が拡大するにつれて、コードの複雑さやスタイル管理の課題が増大します。このような状況に対応するためには、スケーラブルなデザインを意識した設計が欠かせません。

1. プロジェクト規模の拡大による課題

プロジェクトが小規模な段階では、単純なCSSやスタイル管理でも十分に対応可能です。しかし、アプリケーションが成長するにつれて、以下の課題が顕在化します:

コードの混乱

複数の開発者が関与する場合、クラス名やCSSルールが重複しやすく、メンテナンスが難しくなります。

意図しないスタイルの上書き

グローバルスコープで定義されたCSSが意図せず適用され、デザインが崩れることがあります。

スタイルの再利用性の低下

スパゲッティ状のCSSが生じ、新しい機能追加時に既存のコードを流用するのが困難になる場合があります。

2. スケーラブルな設計がもたらすメリット

スケーラブルなデザインを導入することで、以下の利点が得られます:

効率的なコラボレーション

スタイルがモジュール化されていることで、複数の開発者が同時に作業しても干渉を最小限に抑えられます。

メンテナンスの容易さ

CSS Modulesを使用することで、スタイルがコンポーネント単位で管理され、コードベース全体の見通しが良くなります。

デザインの一貫性

スコープが管理されたCSSにより、アプリケーション全体で一貫したデザインが保たれます。

3. CSS Modulesとスケーラブル設計の関係

CSS Modulesは、スケーラブルなデザインの基盤を提供します。コンポーネントごとにスコープを分離することで、スタイルの衝突を防ぎ、独立性を高めます。また、CSS Modulesを組み合わせたフォルダ構成やスタイリング戦略により、将来的な拡張にも柔軟に対応可能です。

4. スケーラビリティが重要なシナリオ

  • 長期間運用されるアプリケーション: 継続的な改修や機能追加に対応する必要があります。
  • 複数人で開発するプロジェクト: チームメンバー間のスタイル競合を避けることが求められます。
  • 多様なUIデザインを持つアプリケーション: デザインパターンを効率的に再利用する必要があります。

スケーラブルなデザインを考慮した設計を導入することで、Reactアプリケーションの成長に伴う課題を解決し、柔軟で保守性の高いコードベースを実現できます。

CSS Modulesを活用したフォルダ構成例

スケーラブルなReactアプリケーションを設計する際には、CSS Modulesを活用したフォルダ構成が重要です。フォルダ構成が整理されていれば、プロジェクトの拡張性とメンテナンス性が大幅に向上します。以下に、効率的な構成例を紹介します。

1. 基本的なフォルダ構成

以下のように、各コンポーネントに対応するCSS Modulesファイルを同じディレクトリ内に配置します。

src/
├── components/
│   ├── Header/
│   │   ├── Header.js
│   │   ├── Header.module.css
│   ├── Footer/
│   │   ├── Footer.js
│   │   ├── Footer.module.css
├── pages/
│   ├── HomePage/
│   │   ├── HomePage.js
│   │   ├── HomePage.module.css
├── styles/
│   ├── globals.css

この構成では、各コンポーネントのスタイルをローカルに管理しつつ、styles/globals.cssで全体のグローバルスタイルを管理します。

2. 機能単位での構成

複数の関連コンポーネントを1つのディレクトリにまとめることで、機能ごとに整理できます。

src/
├── features/
│   ├── Navigation/
│   │   ├── NavBar.js
│   │   ├── NavBar.module.css
│   │   ├── NavItem.js
│   │   ├── NavItem.module.css
│   ├── Authentication/
│   │   ├── LoginForm.js
│   │   ├── LoginForm.module.css

この構成は、特定の機能や画面に関連するコンポーネントをグループ化し、大規模プロジェクトでの管理を容易にします。

3. テーマ対応のフォルダ構成

アプリケーションが複数のテーマ(例: ダークモードとライトモード)をサポートする場合、テーマごとにCSSファイルを分割する方法が有効です。

src/
├── themes/
│   ├── light/
│   │   ├── Header.module.css
│   │   ├── Footer.module.css
│   ├── dark/
│   │   ├── Header.module.css
│   │   ├── Footer.module.css
├── components/
│   ├── Header/
│   │   ├── Header.js
│   │   ├── Header.module.css

この構成では、テーマごとのCSSファイルを切り替える仕組みをReact内で実装できます。

4. プロジェクト規模に応じた構成の選択

  • 小規模プロジェクト: シンプルなコンポーネントごとの構成を採用。
  • 中規模プロジェクト: 機能単位での構成で整理。
  • 大規模プロジェクト: テーマ対応や高度なスケーラビリティを考慮した構成。

適切なフォルダ構成を採用することで、CSS Modulesを効果的に活用し、Reactアプリケーションの拡張性を高めることができます。

コンポーネント単位のスタイリング戦略

CSS Modulesを活用したコンポーネント単位のスタイリングは、Reactアプリケーションの設計をスケーラブルかつメンテナブルにするための鍵です。以下では、効率的なスタイリング戦略を解説します。

1. コンポーネントとCSS Modulesの一対一の関係

基本的な戦略として、1つのReactコンポーネントに対して1つのCSS Modulesファイルを用意する方法があります。これにより、スタイルが完全にそのコンポーネントにスコープされ、他の部分に影響を与えることなく変更が可能です。

// Button.module.css
.button {
  background-color: #007bff;
  color: #fff;
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
}
// Button.js
import React from 'react';
import styles from './Button.module.css';

const Button = ({ text }) => {
  return <button className={styles.button}>{text}</button>;
};

export default Button;

2. 状態に応じたスタイルの適用

CSS Modulesとclassnamesライブラリを組み合わせることで、状態に応じた動的なスタイリングが簡単に実現できます。

// Button.module.css
.button {
  background-color: #007bff;
  color: #fff;
}

.buttonDisabled {
  background-color: #cccccc;
  color: #666666;
}
// Button.js
import React from 'react';
import classNames from 'classnames';
import styles from './Button.module.css';

const Button = ({ text, disabled }) => {
  const buttonClass = classNames(styles.button, {
    [styles.buttonDisabled]: disabled,
  });

  return <button className={buttonClass} disabled={disabled}>{text}</button>;
};

export default Button;

3. 子コンポーネントとのスタイル分離

複雑なコンポーネントの場合、子コンポーネントごとにCSS Modulesファイルを分けることで、スタイルの分離と管理が容易になります。

// Parent.module.css
.parent {
  display: flex;
  justify-content: space-between;
  padding: 20px;
}
// Child.module.css
.child {
  width: 50px;
  height: 50px;
  background-color: #ff5733;
}
// Parent.js
import React from 'react';
import ParentStyles from './Parent.module.css';
import ChildStyles from './Child.module.css';

const Parent = () => {
  return (
    <div className={ParentStyles.parent}>
      <div className={ChildStyles.child}></div>
      <div className={ChildStyles.child}></div>
    </div>
  );
};

export default Parent;

4. ユーティリティクラスの併用

CSS Modulesのメリットを生かしながら、必要に応じてユーティリティクラスを共通化することで効率化を図ることができます。

/* utilities.module.css */
.hidden {
  display: none;
}

.marginTop {
  margin-top: 20px;
}

これらのユーティリティクラスを他のコンポーネントで再利用することで、共通的なスタイルを簡単に適用できます。

5. コンポーネント単位スタイリングのメリット

  • スタイルの分離: コンポーネントごとにスタイルが分離され、影響範囲が明確。
  • 保守性の向上: スタイルの変更が容易で、再利用可能。
  • 開発者間の衝突防止: チーム開発におけるクラス名の競合を防止。

コンポーネント単位のスタイリング戦略を採用することで、CSS Modulesを最大限に活用し、Reactアプリケーションの効率的な設計と開発が可能になります。

グローバルスタイルとのバランス

CSS Modulesはコンポーネント単位のスタイリングに最適ですが、アプリ全体に共通するスタイル(リセットCSSやテーマカラーなど)には、グローバルスタイルが必要です。両者を適切に使い分けることで、効率的かつスケーラブルな設計が実現できます。

1. グローバルスタイルが必要な場面

以下のような要素は、グローバルスタイルで管理するのが適切です。

リセットCSS

ブラウザ間のデフォルトスタイルの違いを統一するためのリセットスタイルは、全体に適用されるべきです。

ベーススタイル

フォントファミリ、背景色、基本的なレイアウトのような、アプリ全体に適用するデザイン要素。

テーマスタイル

ダークモードやライトモードの切り替えに対応するテーマカラーや全体のトーン。

2. グローバルスタイルの管理方法

グローバルスタイルは、通常CSSやSassで定義し、index.cssglobals.cssとして管理します。

/* globals.css */
body {
  margin: 0;
  font-family: Arial, sans-serif;
  background-color: #f5f5f5;
  color: #333;
}

このファイルをindex.jsでインポートし、全体に適用します。

import './styles/globals.css';

3. CSS Modulesとの使い分け

  • グローバルスタイル: 全体に影響を与えるスタイル(リセットCSS、フォント、テーマ)。
  • CSS Modules: コンポーネントに限定されたスタイル。

このように使い分けることで、グローバルスタイルがコンポーネントの独立性を侵害しないようにします。

4. 実践例: グローバルスタイルとCSS Modulesの共存

以下は、グローバルスタイルとCSS Modulesを併用した例です。

/* globals.css */
:root {
  --primary-color: #007bff;
  --secondary-color: #6c757d;
}

body {
  margin: 0;
  font-family: 'Roboto', sans-serif;
}
/* Button.module.css */
.button {
  background-color: var(--primary-color);
  color: #fff;
  padding: 10px;
  border: none;
  border-radius: 5px;
}
// Button.js
import React from 'react';
import styles from './Button.module.css';

const Button = () => {
  return <button className={styles.button}>Click Me</button>;
};

export default Button;

この例では、色やフォントといった共通スタイルはグローバルCSSで管理し、ボタン特有のスタイルはCSS Modulesで定義しています。

5. 注意点

  • スタイルの一貫性を維持: グローバルスタイルがアプリ全体に一貫したデザインを提供します。
  • 過剰な依存を避ける: グローバルスタイルに頼りすぎると、モジュール化の利点が損なわれます。
  • ドキュメント化: グローバルスタイルとCSS Modulesの使い分け基準をチームで明確に定義します。

適切なバランスでグローバルスタイルとCSS Modulesを運用することで、スケーラブルかつ一貫性のあるデザインを実現できます。

応用例: テーマ切り替えの実装

Reactアプリケーションでダークモードやカラーテーマの切り替えを実現することは、ユーザー体験を向上させる重要な要素です。CSS Modulesを活用すると、効率的にテーマ切り替えを実装できます。

1. テーマ切り替えの概要

テーマ切り替えでは、以下のような要素を動的に変更します:

  • 背景色や文字色
  • ボタンやリンクのスタイル
  • グローバルなデザインパターン

CSS Modulesでは、テーマごとに異なるクラスを用意し、状態に応じて動的にクラスを切り替えることで実現します。

2. テーマ用のCSSファイルの準備

以下のように、ダークモードとライトモードのスタイルを定義します。

/* Theme.module.css */
.lightTheme {
  --background-color: #ffffff;
  --text-color: #333333;
}

.darkTheme {
  --background-color: #333333;
  --text-color: #ffffff;
}

.themeContainer {
  background-color: var(--background-color);
  color: var(--text-color);
  padding: 20px;
  border-radius: 5px;
}

3. Reactでテーマ状態を管理

テーマ状態を管理するために、useStateフックを使用します。

import React, { useState } from 'react';
import styles from './Theme.module.css';

const ThemeSwitcher = () => {
  const [isDarkMode, setIsDarkMode] = useState(false);

  const toggleTheme = () => {
    setIsDarkMode((prevMode) => !prevMode);
  };

  const themeClass = isDarkMode ? styles.darkTheme : styles.lightTheme;

  return (
    <div className={`${styles.themeContainer} ${themeClass}`}>
      <p>This is a {isDarkMode ? 'Dark' : 'Light'} Theme</p>
      <button onClick={toggleTheme}>
        Switch to {isDarkMode ? 'Light' : 'Dark'} Theme
      </button>
    </div>
  );
};

export default ThemeSwitcher;

4. テーマ切り替えの実装ポイント

クラスの動的適用

CSS Modulesではクラス名が動的に変更されるため、classnamesライブラリを利用して複数クラスを簡潔に適用できます。

CSS変数の活用

テーマごとのスタイルはCSS変数で管理することで、柔軟性を持たせることができます。変数を使用することで、特定のスタイルを一括で変更可能です。

5. 実践例のデモ

このコードを実行すると、以下の動作が可能です:

  1. ボタンをクリックすると、ダークモードとライトモードが切り替わります。
  2. テーマに応じて、背景色や文字色が動的に変更されます。

6. 拡張可能な設計

  • テーマの永続化: ローカルストレージやクッキーを利用して、選択したテーマを保存。
  • 複数テーマ対応: ダークモードとライトモード以外のカスタムテーマを追加。

7. 注意点

  • CSS Modulesでテーマクラスを管理する場合、クラス名のスコープが維持されているか確認してください。
  • 大規模アプリでは、テーマコンテキストを利用してグローバルに管理すると効率的です。

CSS Modulesを活用することで、テーマ切り替えの実装が簡潔かつスケーラブルになります。この応用例を基に、複雑なUIでも柔軟なテーマ切り替えが可能です。

よくある課題とその解決方法

CSS Modulesを利用する際には、いくつかの課題が発生することがあります。これらの課題を事前に理解し、適切に対応することで、Reactアプリケーションの開発をスムーズに進められます。以下に、よくある課題とその解決方法を解説します。

1. グローバルスタイルの利用とCSS Modulesの混在

課題: CSS Modulesはコンポーネント単位でスコープが分離されるため、グローバルスタイルを必要とする場合に管理が難しくなることがあります。

解決方法:

  • グローバルスタイルはglobals.cssとして明確に分離し、インポートする形で管理。
  • 必要であれば、CSS Modulesで定義したスタイルを明示的にグローバル化する。例えば、:globalセレクタを使用します。
/* globals.css */
:global(body) {
  margin: 0;
  font-family: Arial, sans-serif;
}

2. 状態に応じた動的なクラス名の適用

課題: 複数の状態に応じてクラスを切り替える場合、コードが煩雑になりやすい。

解決方法:

  • classnamesライブラリを使用することで、クラス名の動的な切り替えを簡潔に記述できます。
import classNames from 'classnames';
import styles from './Button.module.css';

const Button = ({ isPrimary, isDisabled }) => {
  const buttonClass = classNames(styles.button, {
    [styles.primary]: isPrimary,
    [styles.disabled]: isDisabled,
  });

  return <button className={buttonClass}>Click Me</button>;
};

3. 長いクラス名の可読性

課題: CSS Modulesが生成するユニークなクラス名が長く、人間にとって読みにくい場合があります。

解決方法:

  • ビルドツール(例: Webpack)の設定を変更して、クラス名のフォーマットを簡略化します。開発中はわかりやすい名前を、運用環境では短い名前を生成するよう設定します。
module.exports = {
  module: {
    rules: [
      {
        test: /\.module\.css$/,
        use: [
          {
            loader: 'css-loader',
            options: {
              modules: {
                localIdentName: '[name]__[local]__[hash:base64:5]',
              },
            },
          },
        ],
      },
    ],
  },
};

4. 大規模プロジェクトでのスタイルの再利用

課題: 同じデザインパターンを複数のコンポーネントで再利用したい場合、スタイルが分散して管理が煩雑になる。

解決方法:

  • 共通のユーティリティスタイルをモジュールとして作成し、必要なコンポーネントでインポートして使用します。
/* utilities.module.css */
.hidden {
  display: none;
}
.marginTop {
  margin-top: 20px;
}
import utilStyles from './utilities.module.css';

const Component = () => {
  return <div className={utilStyles.marginTop}>Hello</div>;
};

5. CSS Modulesの適用範囲外のスタイル制御

課題: CSS Modulesを使用できない場合(例: 外部ライブラリのスタイルを上書きする必要がある)に困ることがあります。

解決方法:

  • 外部ライブラリのスタイルを上書きする場合、:globalを活用するか、インラインスタイルで制御します。
/* Overriding global styles */
:global(.external-library-class) {
  color: red;
}

6. パフォーマンスの最適化

課題: CSS Modulesを多用することで、スタイルシートのサイズやロード時間が増大する可能性があります。

解決方法:

  • 未使用のCSSを削除するためにpurgecsscssnanoを導入し、ビルド後のファイルサイズを最適化。
  • 必要に応じてスタイルをコードスプリッティングし、必要な部分のみをロード。

7. 型安全性の確保

課題: CSS Modulesにおけるクラス名のスペルミスや存在確認が静的に検出できない。

解決方法:

  • TypeScriptを導入し、CSS Modulesの型定義ファイルを生成します。
// styles.module.css.d.ts
declare const styles: {
  [className: string]: string;
};
export default styles;

CSS Modulesを利用する際の課題に対処することで、Reactアプリケーションの開発体験を向上させ、スケーラブルなデザインを効率的に実現できます。

演習問題: CSS Modulesで作る小さなプロジェクト

CSS Modulesを活用した実践的なスキルを身に付けるために、簡単なプロジェクトを作成してみましょう。この演習では、以下の要素を持つシンプルな「To-Doアプリ」を構築します。

目標

  • CSS Modulesを用いたコンポーネント単位のスタイリングを習得する。
  • 動的なクラス切り替えを実装する。
  • グローバルスタイルとCSS Modulesを組み合わせて利用する。

1. プロジェクト構成

以下の構成でプロジェクトを準備します。

src/
├── components/
│   ├── ToDoItem/
│   │   ├── ToDoItem.js
│   │   ├── ToDoItem.module.css
│   ├── ToDoList/
│   │   ├── ToDoList.js
│   │   ├── ToDoList.module.css
├── styles/
│   ├── globals.css
├── App.js

2. グローバルスタイルの設定

全体のスタイルを設定するglobals.cssを作成します。

/* globals.css */
body {
  margin: 0;
  font-family: Arial, sans-serif;
  background-color: #f9f9f9;
  color: #333;
}

3. ToDoItemコンポーネント

個別のTo-Do項目の表示とスタイリングを実装します。

/* ToDoItem.module.css */
.item {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  margin-bottom: 10px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.completed {
  text-decoration: line-through;
  color: #999;
}
// ToDoItem.js
import React from 'react';
import styles from './ToDoItem.module.css';

const ToDoItem = ({ task, isCompleted, toggleComplete }) => {
  return (
    <div
      className={`${styles.item} ${isCompleted ? styles.completed : ''}`}
      onClick={toggleComplete}
    >
      {task}
    </div>
  );
};

export default ToDoItem;

4. ToDoListコンポーネント

To-Doリスト全体を管理するコンポーネントを作成します。

/* ToDoList.module.css */
.container {
  max-width: 400px;
  margin: 50px auto;
  padding: 20px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
// ToDoList.js
import React, { useState } from 'react';
import ToDoItem from '../ToDoItem/ToDoItem';
import styles from './ToDoList.module.css';

const ToDoList = () => {
  const [tasks, setTasks] = useState([
    { id: 1, task: 'Learn React', isCompleted: false },
    { id: 2, task: 'Build a To-Do App', isCompleted: false },
  ]);

  const toggleComplete = (id) => {
    setTasks((prevTasks) =>
      prevTasks.map((task) =>
        task.id === id ? { ...task, isCompleted: !task.isCompleted } : task
      )
    );
  };

  return (
    <div className={styles.container}>
      {tasks.map((task) => (
        <ToDoItem
          key={task.id}
          task={task.task}
          isCompleted={task.isCompleted}
          toggleComplete={() => toggleComplete(task.id)}
        />
      ))}
    </div>
  );
};

export default ToDoList;

5. Appコンポーネント

アプリケーション全体を構築します。

// App.js
import React from 'react';
import ToDoList from './components/ToDoList/ToDoList';
import './styles/globals.css';

const App = () => {
  return <ToDoList />;
};

export default App;

6. 演習のポイント

  • コンポーネント単位のスタイリング: 各コンポーネントでCSS Modulesを利用し、スタイルのスコープを管理。
  • 動的なクラス切り替え: 状態に応じてクラス名を動的に適用。
  • グローバルスタイルとの連携: 基本的なスタイルはグローバルCSSで統一。

7. 拡張タスク

  • 新しいタスクの追加機能を実装する。
  • ダークモード対応を追加する。
  • スタイルのアニメーションを取り入れて、見た目を改善する。

この演習を通して、CSS Modulesの活用方法を実践的に学び、スケーラブルなスタイリングの基礎を身に付けましょう。

まとめ

本記事では、CSS Modulesを活用したReactアプリケーションのスケーラブルな設計手法について解説しました。CSS Modulesの基礎から始まり、利点、実践的なフォルダ構成、コンポーネント単位のスタイリング戦略、グローバルスタイルとの併用、テーマ切り替えの応用例、よくある課題とその解決方法、そして演習課題まで幅広くカバーしました。

CSS Modulesは、スタイルのスコープ管理を強化し、保守性や再利用性を向上させる強力なツールです。適切に利用することで、プロジェクト規模の拡大に対応できる効率的で一貫性のあるスタイル管理が可能になります。これらの知識と実践を通じて、よりスケーラブルで高品質なReactアプリケーションを構築できるようになるでしょう。

コメント

コメントする

目次
  1. CSS Modulesとは?
    1. Reactでの基本的な利用方法
    2. CSS Modulesが生成するクラス名
  2. CSS Modulesの利点
    1. 1. クラス名のスコープ管理
    2. 2. 保守性と再利用性の向上
    3. 3. パフォーマンスの向上
    4. 4. 型安全性のサポート
    5. 5. 開発者体験の向上
  3. スケーラブルなデザインの重要性
    1. 1. プロジェクト規模の拡大による課題
    2. 2. スケーラブルな設計がもたらすメリット
    3. 3. CSS Modulesとスケーラブル設計の関係
    4. 4. スケーラビリティが重要なシナリオ
  4. CSS Modulesを活用したフォルダ構成例
    1. 1. 基本的なフォルダ構成
    2. 2. 機能単位での構成
    3. 3. テーマ対応のフォルダ構成
    4. 4. プロジェクト規模に応じた構成の選択
  5. コンポーネント単位のスタイリング戦略
    1. 1. コンポーネントとCSS Modulesの一対一の関係
    2. 2. 状態に応じたスタイルの適用
    3. 3. 子コンポーネントとのスタイル分離
    4. 4. ユーティリティクラスの併用
    5. 5. コンポーネント単位スタイリングのメリット
  6. グローバルスタイルとのバランス
    1. 1. グローバルスタイルが必要な場面
    2. 2. グローバルスタイルの管理方法
    3. 3. CSS Modulesとの使い分け
    4. 4. 実践例: グローバルスタイルとCSS Modulesの共存
    5. 5. 注意点
  7. 応用例: テーマ切り替えの実装
    1. 1. テーマ切り替えの概要
    2. 2. テーマ用のCSSファイルの準備
    3. 3. Reactでテーマ状態を管理
    4. 4. テーマ切り替えの実装ポイント
    5. 5. 実践例のデモ
    6. 6. 拡張可能な設計
    7. 7. 注意点
  8. よくある課題とその解決方法
    1. 1. グローバルスタイルの利用とCSS Modulesの混在
    2. 2. 状態に応じた動的なクラス名の適用
    3. 3. 長いクラス名の可読性
    4. 4. 大規模プロジェクトでのスタイルの再利用
    5. 5. CSS Modulesの適用範囲外のスタイル制御
    6. 6. パフォーマンスの最適化
    7. 7. 型安全性の確保
  9. 演習問題: CSS Modulesで作る小さなプロジェクト
    1. 目標
    2. 1. プロジェクト構成
    3. 2. グローバルスタイルの設定
    4. 3. ToDoItemコンポーネント
    5. 4. ToDoListコンポーネント
    6. 5. Appコンポーネント
    7. 6. 演習のポイント
    8. 7. 拡張タスク
  10. まとめ