CSS変数によるクラスベースのダークモードトグル
HTML要素の.darkクラスを使用して、CSSカスタムプロパティのオーバーライドとlocalStorage永続化によるユーザー制御のダークモードトグルを実装します。
Dark Mode
詳細な説明
クラスベースのダークモードトグル
prefers-color-schemeは自動ですが、多くのアプリではユーザーに明示的な制御を与えたい場合があります。クラスベースのアプローチは<html>に.darkクラスを追加し、CSS変数をオーバーライドします。
CSS構造
:root {
--bg: #ffffff;
--surface: #f4f4f5;
--text: #18181b;
--text-muted: #71717a;
--primary: #2563eb;
--border: #e4e4e7;
}
html.dark {
--bg: #0a0a0b;
--surface: #141415;
--text: #fafafa;
--text-muted: #a1a1aa;
--primary: #3b82f6;
--border: #27272a;
}
JavaScriptトグル
const toggle = document.getElementById('theme-toggle');
toggle.addEventListener('click', () => {
document.documentElement.classList.toggle('dark');
const isDark = document.documentElement.classList.contains('dark');
localStorage.setItem('theme', isDark ? 'dark' : 'light');
});
誤ったテーマのフラッシュ防止
スタイルシートや本文コンテンツの前に<head>にブロッキングスクリプトを配置します:
<script>
if (localStorage.getItem('theme') === 'dark' ||
(!localStorage.getItem('theme') &&
window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
}
</script>
フレームワーク統合
- Next.js: SSR、ハイドレーション、フラッシュ防止を処理する
next-themesを使用。 - Astro: ブロッキングチェック用に
is:inlineスクリプトを使用。 - プレーンHTML: 上記の
<head>スクリプトがフレームワークなしで動作。
アクセシビリティ
トグルボタンにaria-labelを含め、現在の状態をアナウンスします。スクリーンリーダーに依存するユーザーは、トグルがライトモードとダークモードのどちらに切り替わるかを知る必要があります。
ユースケース
localStorageによる永続化を備えたユーザー向けダークモードトグルボタンが必要なアプリケーションで、フォールバックとしてOSレベルの設定検出と連携する場合。