概要
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はより多機能だが、仕組みを理解するにはこの実装パターンが参考になる