ダークモード
CSS変数を切り替えるだけでダークモードを実現する仕組みを学びます。
ダークモードの正体は「変数の切り替え」
前回のレッスンで、CSS変数を使って色を1箇所で管理する方法を学びました。
:root {
--background: #ffffff;
--text: #171717;
}
body {
background-color: var(--background);
color: var(--text);
}ダークモードの仕組みはとてもシンプルです。この変数の値だけを別のセットに切り替えるだけで実現できます。
新しいCSSの機能を覚える必要はありません。前回学んだCSS変数と、レッスン2で学んだカスケードの組み合わせです。
:root と .dark で2セットの色を定義する
ライトモード用の色は :root に、ダークモード用の色は .dark に定義します。
/* ライトモード(デフォルト) */
:root {
--background: #ffffff;
--text: #171717;
}
/* ダークモード */
.dark {
--background: #171717;
--text: #fafafa;
}ポイントは、変数名は同じで値だけが違うことです。
| 変数名 | ライトモード(:root) | ダークモード(.dark) |
|---|---|---|
| --background | #ffffff(白) | #171717(濃いグレー) |
| --text | #171717(濃いグレー) | #fafafa(明るいグレー) |
body のベーススタイルは var(--background) と var(--text) を参照しているだけなので、変数の値が変われば見た目も自動的に変わります。
HTMLに .dark クラスをつけるだけで切り替わる
ダークモードへの切り替えは、HTMLの <html> 要素に .dark クラスを付けるだけです。
<html>
...
</html><html class="dark">
...
</html>実際に切り替わる様子を確認してみましょう。
ボタンを押すと、背景色と文字色が切り替わります。CSSは一切変更していません。.dark クラスの付け外しだけで、変数の値が切り替わっているのです。
なぜ .dark が :root を上書きできるのか
ここでレッスン2 『カスケードと詳細度』で学んだ詳細度を思い出してください。
:root は疑似クラスセレクタで、.dark はclassです。どちらも詳細度は同じ(class相当)ですが、.dark が :root の後に書かれているため、カスケードの「出現順」ルールで .dark の値が優先されます。
| 詳細度 | 出現順 | |
|---|---|---|
| :root | class相当 | 先に書かれている |
| .dark | class相当 | 後に書かれている → こちらが勝つ |
レッスン2で学んだ「同じ詳細度なら後に書いた方が勝つ」というルールがここで活きています。
.dark クラスが <html> 要素についていないとき、.dark のルールはどの要素にもマッチしないため、:root の値がそのまま使われます。
色を増やしてみよう
実際のサイトでは背景色と文字色だけでなく、ボーダーの色やアクセントカラーなども管理します。
変数が4つに増えましたが、やっていることは同じです。:root と .dark で2セットの値を定義して、コンポーネント側では var() で参照するだけ。色を何個追加しても、この仕組みは変わりません。
このサイトでもダークモードにCSS変数を使っています。
ダークモード 色相 などで検索すると検証してくれてる人がたくさんいるので参考にするとよいです。
構成の概要を振り返ろう
4番目まで理解できましたね。
/* 1. CSSリセット */
*, *::before, *::after { box-sizing: border-box; margin: 0; }
/* 2. ベーススタイル */
body { font-family: system-ui, sans-serif; line-height: 1.6; }
/* 3. デザイントークン(CSS変数) */
:root { --background: #ffffff; --text: #171717; }
/* 4. ダークモードの色定義 */
.dark { --background: #171717; --text: #ffffff; }
/* 5. レスポンシブなサイズ定義 */
h1 { font-size: clamp(1.5rem, 1.25rem + 1vw, 1.875rem); }/* 1. CSSリセット ✅ */
*, *::before, *::after { box-sizing: border-box; margin: 0; }
/* 2. ベーススタイル ✅ */
body { font-family: system-ui, sans-serif; line-height: 1.6; }
/* 3. デザイントークン(CSS変数) ✅ */
:root { --background: #ffffff; --text: #171717; }
/* 4. ダークモードの色定義 ✅ */
.dark { --background: #171717; --text: #ffffff; }残りは 5. レスポンシブなサイズ定義 です。
次のステップ
ダークモードの仕組みを学びました。次のレッスンでは、よりモダンな手法として、画面幅に応じてサイズを滑らかに変化させる clamp() を学びます。