CSSとJavaScriptでダークモードトグルを構築する方法
ダークモードは、現代のウェブサイトにとって不可欠な機能となっています。ユーザーは、環境、時間帯、または個人の好みに応じてテーマを切り替えることを期待しています。このチュートリアルでは、システム設定を尊重し、ユーザーの選択を記憶し、最適なパフォーマンスのために最新のCSS機能を活用する、堅牢なダークモードトグルの構築方法を紹介します。
重要なポイント
- システム設定を尊重し、ユーザーの選択を保持するダークモードトグルを構築
- 効率的なテーマ設定のためにCSSカスタムプロパティとcolor-schemeプロパティを使用
- ページ読み込み時のスタイル未適用コンテンツのフラッシュを防ぐJavaScriptを実装
- キーボードナビゲーションとスクリーンリーダーのアクセシビリティベストプラクティスを適用
HTML構造のセットアップ
トグルボタンを含み、初期テーマを宣言するセマンティックHTMLから始めます:
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>Dark Mode Toggle Demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<button type="button" id="theme-toggle" aria-label="Toggle dark mode">
<span class="toggle-text">Dark</span>
</button>
<!-- Your content here -->
</body>
</html>
HTML要素のdata-theme属性がテーマを制御します。color-schemeメタタグは、スクロールバーやフォームコントロールなどのネイティブUI要素を適応させるようブラウザに指示します。
最新機能を使用したCSSの実装
CSSカスタムプロパティとcolor-schemeの使用
CSSカスタムプロパティを使用してカラートークンを定義し、ネイティブ要素のテーマ設定のためにCSS color-schemeプロパティを活用します:
:root {
color-scheme: light dark;
/* Light theme colors (default) */
--bg-color: #ffffff;
--text-color: #213547;
--accent-color: #0066cc;
}
[data-theme="dark"] {
--bg-color: #1a1a1a;
--text-color: #e0e0e0;
--accent-color: #66b3ff;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s ease, color 0.3s ease;
}
prefers-color-schemeでシステム設定を尊重
prefers-color-schemeのサポートを追加して、システム設定に自動的に合わせます:
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--bg-color: #1a1a1a;
--text-color: #e0e0e0;
--accent-color: #66b3ff;
}
}
最新のlight-dark()関数
light-dark()関数をサポートするブラウザでは、カラー定義を簡素化できます:
:root {
color-scheme: light dark;
}
body {
background-color: light-dark(#ffffff, #1a1a1a);
color: light-dark(#213547, #e0e0e0);
}
この関数は、アクティブなカラースキームに基づいて適切な色を自動的に選択し、コードの重複を削減します。
Discover how at OpenReplay.com.
トグルと永続化のためのJavaScript
読み込み時のテーマフラッシュの防止
スタイル未適用コンテンツのフラッシュを防ぐため、このスクリプトを<body>開始タグの直後に配置します:
<script>
// Apply saved theme immediately to prevent flash
(function() {
const saved = localStorage.getItem('theme');
if (saved) {
document.documentElement.setAttribute('data-theme', saved);
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-theme', 'dark');
}
})();
</script>
完全なダークモード実装
トグル機能のために、このJavaScriptを追加します:
const toggle = document.getElementById('theme-toggle');
const html = document.documentElement;
// Get current theme
function getTheme() {
return html.getAttribute('data-theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
}
// Set theme and update UI
function setTheme(theme) {
html.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
updateToggleText(theme);
}
// Update button text
function updateToggleText(theme) {
const text = toggle.querySelector('.toggle-text');
text.textContent = theme === 'dark' ? 'Light' : 'Dark';
toggle.setAttribute('aria-label', `Switch to ${theme === 'dark' ? 'light' : 'dark'} mode`);
}
// Initialize
updateToggleText(getTheme());
// Handle toggle click
toggle.addEventListener('click', () => {
const current = getTheme();
setTheme(current === 'dark' ? 'light' : 'dark');
});
// Listen for system preference changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
if (!localStorage.getItem('theme')) {
setTheme(e.matches ? 'dark' : 'light');
}
});
アクセシビリティとベストプラクティス
必須のアクセシビリティ機能
ダークモードトグルは、キーボードでアクセス可能で、適切にラベル付けされている必要があります:
#theme-toggle:focus-visible {
outline: 2px solid var(--accent-color);
outline-offset: 2px;
}
両方のテーマで十分な色のコントラストを確保してください。ダークモードは低コントラストを意味するものではありません。少なくともWCAG AA基準(通常のテキストで4.5:1)を維持してください。
避けるべきこと
ページ全体にfilter: invert(1)を使用しないでください。画像やメディアが不必要に反転されます。ダークモードで純粋な黒(#000000)の背景を避けてください。読みやすさを向上させるために、ダークグレー(#1a1a1a)を使用してください。CSSフォールバックなしでJavaScriptのみに依存しないでください。
実装のテスト
さまざまなシナリオでダークモードトグルをテストします:
- localStorageをクリアして、システム設定の検出が機能することを確認
- テーマを切り替えて更新し、永続化を確認
- サイトが開いている間にシステム設定を変更
- ブラウザのDevToolsを使用してコントラスト比を確認
- キーボードナビゲーションとスクリーンリーダーのアナウンスをテスト
まとめ
適切に実装されたダークモードソリューションは、ユーザーの好みを尊重し、選択を保持し、最新のCSS機能を活用します。color-schemeプロパティ、カスタムプロパティ、最小限のJavaScriptを組み合わせることで、パフォーマンスが高く、アクセシブルで、ユーザーフレンドリーなテーマスイッチャーを作成できます。light-dark()関数は最新のブラウザのカラー管理を簡素化し、フォールバックは互換性を保証します。
覚えておいてください:最良のダークモード実装は、ユーザーには見えないものです。ユーザーが期待する通りに機能するだけです。
よくある質問
はい、prefers-color-schemeを使用したCSSメディアクエリでシステム設定を検出できます。ただし、ユーザーの好みを保存し、システム設定を上書きする手動トグルボタンを提供するにはJavaScriptが必要です。
これは、ページのレンダリング後にJavaScriptが実行される場合に発生します。このフラッシュを防ぐには、bodyタグの直後にlocalStorageをチェックし、ページの描画前に保存されたテーマを適用するスクリプトを配置してください。
いいえ、純粋な黒は目の疲労を引き起こし、テキストを読みにくくする可能性があります。代わりに、#1a1a1aや#121212のようなダークグレーを使用してください。これらの色は疲労を軽減しながら、アクセシビリティのための良好なコントラスト比を維持します。
画像にfilter invertを使用しないでください。代わりに、ダークモード用の代替バージョンの画像を提供するか、両方の背景で機能する色の透明PNGを使用してください。複雑なグラフィックの場合は、CSSマスクやcurrentColorを使用したSVGの使用を検討してください。
Truly understand users experience
See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..