Tailwind CSS ダークモードとテーマ設定:dark プレフィックスと @theme ディレクティブ

ダークモード (dark:)

Tailwindはdark:プレフィックスを使用してダークモード用のスタイルを定義します。mediaclassの両方の戦略をサポートしています。

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ダークモードデモ</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <script>
    tailwind.config = {
      darkMode: 'class'
    }
  </script>
</head>
<body class="min-h-screen bg-white dark:bg-gray-900 transition-colors">
  <div class="max-w-4xl mx-auto p-8 space-y-8">
    <!-- ダークモード切替ボタン -->
    <div class="flex justify-end">
      <button onclick="document.documentElement.classList.toggle('dark')"
              class="p-2 rounded-lg bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200">
        ダークモード切替
      </button>
    </div>

    <!-- テキスト色 -->
    <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
      <h3 class="text-gray-900 dark:text-white font-semibold text-lg mb-4">テキスト色</h3>
      <p class="text-gray-600 dark:text-gray-300">
        このテキストはライトモードではダークグレー、ダークモードではライトグレーで表示されます。
      </p>
      <p class="text-blue-600 dark:text-blue-400 mt-2">
        リンクの色もモードに応じて変化します。
      </p>
    </div>

    <!-- カードコンポーネント -->
    <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg dark:shadow-gray-700/50 p-6">
        <div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-lg flex items-center justify-center mb-4">
          <span class="text-blue-600 dark:text-blue-400 text-xl">🎨</span>
        </div>
        <h4 class="text-gray-900 dark:text-white font-semibold mb-2">テーマ適応</h4>
        <p class="text-gray-600 dark:text-gray-400">カードの背景、シャドウ、テキスト色がすべてダークモードに適応します。</p>
      </div>
      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg dark:shadow-gray-700/50 p-6">
        <div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-lg flex items-center justify-center mb-4">
          <span class="text-green-600 dark:text-green-400 text-xl">✨</span>
        </div>
        <h4 class="text-gray-900 dark:text-white font-semibold mb-2">スムーズな切り替え</h4>
        <p class="text-gray-600 dark:text-gray-400">transition-colors と組み合わせて滑らかな色切り替えを実現。</p>
      </div>
    </div>

    <!-- フォーム要素 -->
    <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
      <h3 class="text-gray-900 dark:text-white font-semibold mb-4">フォーム要素</h3>
      <div class="space-y-4">
        <input type="text" placeholder="入力フィールド"
               class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-gray-500 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400">
        <button class="w-full p-3 bg-blue-600 dark:bg-blue-500 text-white rounded-lg hover:bg-blue-700 dark:hover:bg-blue-600 transition-colors">
          送信ボタン
        </button>
      </div>
    </div>
  </div>
</body>
</html>
▶ 試してみよう

従来のCSSとTailwindの比較 従来の方法では@media (prefers-color-scheme: dark)を書いたり、.darkクラスを手動で追加して多数のCSSルールを書く必要がありますが、Tailwindではdark:bg-gray-900 dark:text-whiteのようなプレフィックスでインライン宣言できます。

💡 ポイント: darkMode: 'class'戦略では<html>要素のdarkクラスを切り替える必要があります。darkMode: 'media'戦略はシステム設定に自動的に従います。

カスタムテーマ (tailwind.config)

tailwind.configファイルを通じてデフォルトテーマを拡張または上書きし、カスタム色、フォント、間隔などを追加できます。

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>カスタムテーマデモ</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: {
              50: '#eff6ff',
              100: '#dbeafe',
              200: '#bfdbfe',
              300: '#93c5fd',
              400: '#60a5fa',
              500: '#3b82f6',
              600: '#2563eb',
              700: '#1d4ed8',
              800: '#1e40af',
              900: '#1e3a8a',
            },
            accent: '#f59e0b',
            brand: '#8b5cf6',
          },
          fontFamily: {
            sans: ['Inter', 'system-ui', 'sans-serif'],
            display: ['Poppins', 'sans-serif'],
          },
          spacing: {
            '128': '32rem',
            '144': '36rem',
          },
          borderRadius: {
            '4xl': '2rem',
          },
        },
      },
    }
  </script>
</head>
<body class="min-h-screen bg-gray-100 p-8">
  <div class="max-w-4xl mx-auto space-y-8">
    <!-- カスタムカラー -->
    <div class="bg-white rounded-lg shadow p-6">
      <h3 class="font-semibold mb-4">カスタムカラー</h3>
      <div class="flex flex-wrap gap-4">
        <div class="w-20 h-20 bg-primary-500 rounded-lg flex items-center justify-center text-white text-xs">primary-500</div>
        <div class="w-20 h-20 bg-primary-600 rounded-lg flex items-center justify-center text-white text-xs">primary-600</div>
        <div class="w-20 h-20 bg-primary-700 rounded-lg flex items-center justify-center text-white text-xs">primary-700</div>
        <div class="w-20 h-20 bg-accent rounded-lg flex items-center justify-center text-white text-xs">accent</div>
        <div class="w-20 h-20 bg-brand rounded-lg flex items-center justify-center text-white text-xs">brand</div>
      </div>
    </div>

    <!-- カスタムフォント -->
    <div class="bg-white rounded-lg shadow p-6">
      <h3 class="font-semibold mb-4">カスタムフォント</h3>
      <p class="font-sans text-lg mb-2">font-sans: Inter フォントを使用</p>
      <p class="font-display text-lg">font-display: Poppins フォントを使用</p>
    </div>

    <!-- カスタム間隔 -->
    <div class="bg-white rounded-lg shadow p-6">
      <h3 class="font-semibold mb-4">カスタム間隔</h3>
      <div class="space-y-2">
        <div class="h-4 bg-primary-200 rounded" style="width: 32rem;">
          <span class="text-xs">w-128 (32rem)</span>
        </div>
        <div class="h-4 bg-primary-300 rounded" style="width: 36rem;">
          <span class="text-xs">w-144 (36rem)</span>
        </div>
      </div>
    </div>

    <!-- カスタムボーダー半径 -->
    <div class="bg-white rounded-lg shadow p-6">
      <h3 class="font-semibold mb-4">カスタムボーダー半径</h3>
      <div class="flex gap-4">
        <div class="w-24 h-24 bg-brand rounded-4xl flex items-center justify-center text-white text-xs">rounded-4xl</div>
        <div class="w-24 h-24 bg-accent rounded-full flex items-center justify-center text-white text-xs">rounded-full</div>
      </div>
    </div>
  </div>
</body>
</html>
▶ 試してみよう

従来のCSSとTailwindの比較 従来の方法ではCSSに多数の変数とクラスを定義する必要がありますが、Tailwindではtailwind.configextendオプションでテーマを拡張し、対応するユーティリティクラスが自動生成されます。

@theme ディレクティブ(v4 新機能)

Tailwind v4では@themeディレクティブが導入され、JavaScript設定ファイルなしでCSSネイティブな構文を使ってテーマ変数を定義できます。

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>@theme ディレクティブデモ</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <style type="text/tailwindcss">
    @theme {
      --color-primary-50: #eff6ff;
      --color-primary-100: #dbeafe;
      --color-primary-200: #bfdbfe;
      --color-primary-300: #93c5fd;
      --color-primary-400: #60a5fa;
      --color-primary-500: #3b82f6;
      --color-primary-600: #2563eb;
      --color-primary-700: #1d4ed8;
      --color-primary-800: #1e40af;
      --color-primary-900: #1e3a8a;

      --color-accent: #f59e0b;
      --color-brand: #8b5cf6;

      --font-sans: 'Inter', system-ui, sans-serif;
      --font-display: 'Poppins', sans-serif;

      --spacing-128: 32rem;
      --spacing-144: 36rem;

      --radius-4xl: 2rem;
    }
  </style>
</head>
<body class="min-h-screen bg-gray-100 p-8">
  <div class="max-w-4xl mx-auto space-y-8">
    <!-- @theme で定義した色 -->
    <div class="bg-white rounded-lg shadow p-6">
      <h3 class="font-semibold mb-4">@theme で定義した色</h3>
      <div class="flex flex-wrap gap-4">
        <div class="w-20 h-20 bg-primary-500 rounded-lg flex items-center justify-center text-white text-xs">primary-500</div>
        <div class="w-20 h-20 bg-primary-600 rounded-lg flex items-center justify-center text-white text-xs">primary-600</div>
        <div class="w-20 h-20 bg-accent rounded-lg flex items-center justify-center text-white text-xs">accent</div>
        <div class="w-20 h-20 bg-brand rounded-lg flex items-center justify-center text-white text-xs">brand</div>
      </div>
    </div>

    <!-- @theme で定義したフォント -->
    <div class="bg-white rounded-lg shadow p-6">
      <h3 class="font-semibold mb-4">@theme で定義したフォント</h3>
      <p class="font-sans text-lg mb-2">font-sans: Inter フォントを使用</p>
      <p class="font-display text-lg">font-display: Poppins フォントを使用</p>
    </div>

    <!-- @theme で定義した間隔 -->
    <div class="bg-white rounded-lg shadow p-6">
      <h3 class="font-semibold mb-4">@theme で定義した間隔</h3>
      <div class="space-y-2">
        <div class="h-4 bg-primary-200 rounded w-128">
          <span class="text-xs">w-128 (32rem)</span>
        </div>
        <div class="h-4 bg-primary-300 rounded w-144">
          <span class="text-xs">w-144 (36rem)</span>
        </div>
      </div>
    </div>

    <!-- @theme で定義したボーダー半径 -->
    <div class="bg-white rounded-lg shadow p-6">
      <h3 class="font-semibold mb-4">@theme で定義したボーダー半径</h3>
      <div class="flex gap-4">
        <div class="w-24 h-24 bg-brand rounded-4xl flex items-center justify-center text-white text-xs">rounded-4xl</div>
      </div>
    </div>
  </div>
</body>
</html>
▶ 試してみよう

従来のCSSとTailwindの比較 従来の方法ではtailwind.config.jsでJavaScriptオブジェクトを使ってテーマを定義する必要がありますが、Tailwind v4の@themeディレクティブはCSSネイティブな変数構文を使用し、より直感的でネイティブCSS変数との互換性があります。

💡 ポイント: @themeディレクティブの変数名は--color-*--font-*--spacing-*--radius-*などの命名規則に従います。Tailwindが対応するユーティリティクラスを自動生成します。

CSS ネイティブ変数と Tailwind の統合

Tailwind v4はCSSネイティブ変数を直接使用でき、設定ファイルを経由する必要がありません。

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS ネイティブ変数の統合</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <style>
    :root {
      --main-bg: #f8fafc;
      --card-bg: #ffffff;
      --text-primary: #1e293b;
      --text-secondary: #64748b;
      --border-color: #e2e8f0;
      --spacing-section: 2rem;
    }

    .dark {
      --main-bg: #0f172a;
      --card-bg: #1e293b;
      --text-primary: #f1f5f9;
      --text-secondary: #94a3b8;
      --border-color: #334155;
    }
  </style>
</head>
<body class="min-h-screen p-8" style="background-color: var(--main-bg);">
  <div class="max-w-4xl mx-auto space-y-8" style="gap: var(--spacing-section);">
    <!-- ダークモード切替 -->
    <div class="flex justify-end">
      <button onclick="document.documentElement.classList.toggle('dark')"
              class="p-2 rounded-lg" style="background-color: var(--card-bg); color: var(--text-primary);">
        ダークモード切替
      </button>
    </div>

    <!-- CSS 変数を使用したカード -->
    <div class="rounded-lg shadow p-6" style="background-color: var(--card-bg); border: 1px solid var(--border-color);">
      <h3 class="font-semibold text-lg mb-4" style="color: var(--text-primary);">CSS ネイティブ変数</h3>
      <p style="color: var(--text-secondary);">
        このカードはCSSネイティブ変数を使って色を定義し、style属性で適用しています。
      </p>
    </div>

    <!-- 混合使用 -->
    <div class="rounded-lg shadow p-6 bg-white dark:bg-gray-800">
      <h3 class="font-semibold text-lg mb-4 text-gray-900 dark:text-white">混合使用</h3>
      <p class="text-gray-600 dark:text-gray-300 mb-4">
        TailwindクラスとCSS変数を組み合わせて使用できます。
      </p>
      <div class="flex gap-4">
        <div class="w-16 h-16 rounded-lg" style="background-color: var(--text-primary);"></div>
        <div class="w-16 h-16 rounded-lg bg-blue-500"></div>
        <div class="w-16 h-16 rounded-lg" style="background-color: var(--border-color);"></div>
      </div>
    </div>
  </div>
</body>
</html>
▶ 試してみよう
💡 ポイント: CSSネイティブ変数は実行時に動的に変更する必要がある値(テーマ切り替えなど)に最も適しており、Tailwindクラスは静的なスタイルに適しています。

プラグインシステム入門

Tailwindプラグインは、カスタムユーティリティクラス、バリアント、ベーススタイルを追加してフレームワークの機能を拡張できます。

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>プラグインシステムデモ</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <script>
    const plugin = tailwind.plugin;

    // カスタムプラグイン:テキストグラデーションユーティリティクラスを追加
    const textGradientPlugin = plugin(function({ addUtilities }) {
      addUtilities({
        '.text-gradient-blue': {
          'background': 'linear-gradient(to right, #3b82f6, #8b5cf6)',
          '-webkit-background-clip': 'text',
          '-webkit-text-fill-color': 'transparent',
          'background-clip': 'text',
        },
        '.text-gradient-red': {
          'background': 'linear-gradient(to right, #ef4444, #f97316)',
          '-webkit-background-clip': 'text',
          '-webkit-text-fill-color': 'transparent',
          'background-clip': 'text',
        },
      });
    });

    tailwind.config = {
      plugins: [textGradientPlugin],
    }
  </script>
</head>
<body class="min-h-screen bg-gray-100 p-8">
  <div class="max-w-4xl mx-auto space-y-8">
    <!-- プラグインで追加したユーティリティクラス -->
    <div class="bg-white rounded-lg shadow p-6">
      <h3 class="font-semibold mb-4">カスタムプラグイン:テキストグラデーション</h3>
      <p class="text-4xl font-bold text-gradient-blue mb-4">青のグラデーションテキスト</p>
      <p class="text-4xl font-bold text-gradient-red">赤のグラデーションテキスト</p>
    </div>

    <!-- 一般的なサードパーティプラグインの例 -->
    <div class="bg-white rounded-lg shadow p-6">
      <h3 class="font-semibold mb-4">一般的なプラグイン</h3>
      <div class="space-y-4">
        <div class="p-4 bg-gray-50 rounded-lg">
          <h4 class="font-medium text-gray-900">@tailwindcss/typography</h4>
          <p class="text-gray-600 text-sm">prose クラスを使用して、長文コンテンツに美しいタイポグラフィスタイルを提供します。</p>
        </div>
        <div class="p-4 bg-gray-50 rounded-lg">
          <h4 class="font-medium text-gray-900">@tailwindcss/forms</h4>
          <p class="text-gray-600 text-sm">フォーム要素のベーススタイルリセットを提供し、ブラウザ間で一貫した動作を確保します。</p>
        </div>
        <div class="p-4 bg-gray-50 rounded-lg">
          <h4 class="font-medium text-gray-900">@tailwindcss/aspect-ratio</h4>
          <p class="text-gray-600 text-sm">要素の幅と高さの比率を制御する aspect-ratio ユーティリティクラスを提供します。</p>
        </div>
      </div>
    </div>
  </div>
</body>
</html>
▶ 試してみよう

従来のCSSとTailwindの比較 従来の方法ではCSSクラスを手動で書いてインポートする必要がありますが、TailwindプラグインはaddUtilitiesaddComponentsaddBaseなどのAPIを通じてビルドプロセスに自動的に統合されます。

⚠️ 注意: Tailwind v4ではプラグインAPIが変更されました。CSSネイティブなアプローチで機能を拡張することが推奨されています。@themeディレクティブと@layerでほとんどのプラグインのユースケースを置き換えることができます。

❓ よくある質問

Q darkMode: 'class' と darkMode: 'media' の違いは何ですか?
A 'media'戦略はシステムのprefers-color-schemeメディアクエリに自動的に従い、ユーザーが手動で切り替えることはできません。'class'戦略は<html>要素のdarkクラスを手動で切り替える必要があり、切替ボタンを提供する場合に適しています。
Q @theme ディレクティブと tailwind.config の違いは何ですか?
A tailwind.configはJavaScriptオブジェクトでテーマを定義し、設定ファイルが必要です。@themeディレクティブはCSSネイティブな変数構文を使用し、CSS内に直接定義します。Tailwind v4の新機能であり、推奨されるアプローチです。
Q ダークモードで異なる画像を使用するにはどうすればよいですか?
A dark:プレフィックスとhiddenblockを組み合わせて使用します。例:<img class="block dark:hidden" src="light.png"><img class="hidden dark:block" src="dark.png">
Q CSS変数とTailwindクラスはどう使い分けるべきですか?
A 静的なスタイルにはTailwindクラスを優先し、実行時に動的に変更する必要がある値にはCSS変数を使用してください。両方を混合でき、例えばstyle="color: var(--text-primary)"のように使用できます。

📖 まとめ

📝 課題

  1. dark:プレフィックスを使って入力フィールド、ボタン、カードのすべての要素を適応させたダークモード対応のログインページを作成してください

  2. ⭐⭐ @themeディレクティブを使ってブランドテーマ(primary色、secondary色、フォントを含む)をカスタマイズし、ショーケースページを作成してください

  3. ⭐⭐⭐ ライト/ダーク/システムの3モードに対応したテーマスイッチャーを作成し、CSS変数で動的なテーマ色の切り替えを実現してください

100%