data-theme 属性を切り替えるだけで、ページ全体のカラーテーマを変更できます。CSSカスタムプロパティとTailwind CSSを組み合わせた実装方法を紹介します。ReactとTailwind CSSでの実装例を示しますが、他のフレームワークでも同じアプローチが使えます。
CSSカスタムプロパティで管理するメリット
CSS変数でテーマを管理する利点は、変更の影響範囲をCSS側に閉じ込められる点です。
- JavaScriptからの操作が
setAttributeの1行で完了する - 色の変更がCSS変数の定義箇所だけで完結し、コンポーネントに波及しない
- ブラウザーの開発者ツールでCSS変数の値をリアルタイムに変更してデバッグできる
新しいテーマの追加も :root[data-theme="新テーマ名"] にCSS変数を定義するだけで済みます。コンポーネントのスタイリングコードを触る必要はありません。
CSSカスタムプロパティでテーマを定義する
テーマの色をCSSカスタムプロパティ(変数)として定義します。:root にデフォルトテーマ、data-theme 属性付きのセレクターに別テーマの値を設定します。
:root { /* デフォルトテーマ */
--background-color: #fcfcfc;
--foreground-color: #333;
--primary-color-50: #fff1f3;
--primary-color-100: #ffdfe4;
/* ... 中間の色は省略 ... */
--primary-color-900: #891325;
--primary-color-950: #4b040f;
--secondary-color-50: #eefffb;
--secondary-color-100: #c4fff3;
/* ... 中間の色は省略 ... */
--secondary-color-900: #095850;
--secondary-color-950: #003634;
}
ダークテーマなどの別テーマも同じ変数名で定義します。
:root[data-theme="dark"] {
--background-color: #333;
--foreground-color: #f5f5f5;
--primary-color-50: #feffe7;
/* ... 色定義 ... */
--secondary-color-50: #edfffc;
/* ... 色定義 ... */
}
data-theme 属性の値を切り替えるだけで、全ページの色が一括で変わります。
カラーパレットを設計する
50〜950のカラーパレットを作成する場合、以下のツールが便利です。
- Adobe Color … カラーパレットの閲覧・作成
- Color Hunt … カラーパレットのギャラリー
- Color wheel … 指定色の補色・類似色の算出
- Tailwind CSS Color Generator … 1色のRGBからTailwind用の50〜950を自動生成
Tailwind CSSを使う場合、Tailwind CSS Color Generatorは必須です。ベースカラーを1つ指定するだけで、50〜950のパレット全体を生成してくれます。
Tailwind CSSの設定
TailwindのconfigでCSS変数を参照するように記述します。
tailwind.config = {
theme: {
extend: {
colors: {
background: "var(--background-color)",
foreground: "var(--foreground-color)",
primary: {
"50": "var(--primary-color-50)",
"100": "var(--primary-color-100)",
// ... 中間の色は省略 ...
"900": "var(--primary-color-900)",
"950": "var(--primary-color-950)",
},
secondary: {
"50": "var(--secondary-color-50)",
"100": "var(--secondary-color-100)",
// ... 中間の色は省略 ...
"900": "var(--secondary-color-900)",
"950": "var(--secondary-color-950)",
},
},
},
},
};
この設定により、bg-primary-500 や text-secondary-300 といったTailwindのユーティリティクラスがCSS変数の値を参照するようになります。テーマごとにクラス名を変更する必要はありません。
テーマ切り替えの実装
テーマの切り替えは、data-theme 属性の書き換えだけで完了します。
type ColorScheme = "default" | "dark" | "custom";
const App = () => {
const [colorScheme, setColorScheme] = React.useState<ColorScheme>("default");
React.useEffect(() => {
document.documentElement.setAttribute("data-theme", colorScheme);
}, [colorScheme]);
return (
<div className="min-h-screen bg-background text-foreground">
<div className="flex items-center justify-center">
<label htmlFor="color-scheme" className="text-lg font-bold mb-2 mr-4">
Color Scheme
</label>
<select
id="color-scheme"
value={colorScheme}
onChange={(e) => setColorScheme(e.target.value as ColorScheme)}
className="p-2 border border-gray-300 rounded-md"
>
<option value="default">Default</option>
<option value="dark">Dark</option>
<option value="custom">Custom</option>
</select>
</div>
<div className="mt-8">
<button className="px-4 py-2 bg-primary-500 text-white rounded-md">
Primary Button
</button>
<button className="ml-4 px-4 py-2 bg-secondary-500 text-white rounded-md">
Secondary Button
</button>
</div>
</div>
);
};
colorScheme の状態が変わると useEffect が data-theme 属性を更新し、CSS変数の値が切り替わります。コンポーネント側のクラス名は一切変更する必要がありません。
動作確認は冒頭のCodepenで試せます。
CodePenTailwind CSS Color Theme DemoCSS カスタムプロパティと Tailwind CSS を使ったカラーテーマ切り替えデモです。