レビュー済み·難易度: 初級·更新: 2026-04-18

Tailwind CSS でダークモードを実装する(class strategy + localStorage)

Tailwind の class strategy と useState / localStorage を組み合わせてダークモードを実装する例。next-themes を使わずに自前でテーマ切り替えを管理する。

nextjsstylingtailwindcss

対応バージョン

nextjs 15react 19tailwindcss 4

前提環境

Tailwind CSS の基本的なクラスを理解していること

概要

Tailwind CSS の dark: プレフィックスと <html> 要素への dark クラス付与を組み合わせてダークモードを実装する。localStorage にテーマ設定を保存してリロード後も状態を維持する。next-themes に依存せず、仕組みを最小限のコードで理解できる構成。

インストール

npm install tailwindcss

実装

テーマ切り替えフック

// hooks/useTheme.ts
"use client";

import { useEffect, useState } from "react";

type Theme = "light" | "dark";

export function useTheme() {
  const [theme, setTheme] = useState<Theme>("light");

  useEffect(() => {
    const stored = localStorage.getItem("theme") as Theme | null;
    if (stored) {
      setTheme(stored);
      applyTheme(stored);
    } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
      setTheme("dark");
      applyTheme("dark");
    }
  }, []);

  function applyTheme(next: Theme) {
    const root = document.documentElement;
    if (next === "dark") {
      root.classList.add("dark");
    } else {
      root.classList.remove("dark");
    }
  }

  function toggle() {
    const next: Theme = theme === "light" ? "dark" : "light";
    setTheme(next);
    applyTheme(next);
    localStorage.setItem("theme", next);
  }

  return { theme, toggle };
}

テーマ切り替えボタン

// components/ThemeToggle.tsx
"use client";

import { useTheme } from "@/hooks/useTheme";

export function ThemeToggle() {
  const { theme, toggle } = useTheme();

  return (
    <button
      onClick={toggle}
      className="rounded-md border border-gray-300 px-4 py-2 text-sm
                 bg-white text-gray-800
                 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100"
    >
      {theme === "light" ? "ダークモードにする" : "ライトモードにする"}
    </button>
  );
}

ページでの使用例

// app/page.tsx
import { ThemeToggle } from "@/components/ThemeToggle";

export default function Page() {
  return (
    <main className="min-h-screen bg-white text-gray-900 dark:bg-gray-900 dark:text-gray-100">
      <div className="mx-auto max-w-2xl p-8">
        <h1 className="mb-6 text-2xl font-bold">ダークモードサンプル</h1>
        <ThemeToggle />
        <p className="mt-4 text-gray-600 dark:text-gray-400">
          このテキストはテーマに応じて色が変わります。
        </p>
      </div>
    </main>
  );
}

ポイント

  • document.documentElement<html> 要素)に dark クラスを付与・除去することでテーマを切り替える
  • Tailwind v4 はデフォルトで class-based dark mode に対応しており、tailwind.config での darkMode: 'class' 設定は不要
  • localStorage に保存することでページリロード後もテーマを維持できる
  • useEffect 内で window.matchMedia を参照し、OS のカラースキーム設定を初期値として使う
  • next-themes はより多機能だが、仕組みを理解するにはこの実装パターンが参考になる

注意点

Tailwind v4 では darkMode: 'class' の設定が不要になり、デフォルトで class ベースに対応している。

関連サンプル