ダークモードとは——現代UIの必須機能
ダークモードは、背景を暗くしてテキストを明るくするUIテーマです。目の疲れの軽減・バッテリー消費の削減(OLED端末)・視認性向上などのメリットから、macOS・iOS・Androidなど主要OSで標準サポートされています。
ユーザーがOSのダークモード設定をしている場合、Webサイトもそれに追従することで一貫したUXを提供できます。
Tailwind CSSのダークモード設定
Tailwind CSSには2つのダークモード戦略があります。
1. media(OS設定に連動)
// tailwind.config.js
module.exports = {
darkMode: 'media', // prefers-color-scheme: dark に連動
// ...
}
<!-- dark: プレフィックスで暗色時のスタイルを指定 -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
<p>OS設定のダークモードに自動追従</p>
</div>
2. class(手動切り替え)
// tailwind.config.js
module.exports = {
darkMode: 'class', // <html class="dark"> があれば暗色モード
// ...
}
弊社では class 戦略を採用しています。ユーザーがボタンで切り替え、設定を localStorage に保存することで次回訪問時も維持できます。
トグルボタンの実装
<!-- ダークモード切り替えボタン -->
<button
id="theme-toggle"
class="p-2 rounded-full bg-gray-100 dark:bg-gray-800
text-gray-600 dark:text-gray-300
hover:bg-gray-200 dark:hover:bg-gray-700
transition-colors duration-200"
aria-label="ダークモード切り替え"
>
<!-- 太陽アイコン(ライトモード時に表示) -->
<svg id="icon-sun" class="w-5 h-5 hidden dark:block" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
<!-- 月アイコン(ダークモード時に表示) -->
<svg id="icon-moon" class="w-5 h-5 block dark:hidden" fill="currentColor" viewBox="0 0 20 20">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"/>
</svg>
</button>
JavaScriptでの切り替えロジック
// テーマの初期化(ページ読み込み時)
function initTheme() {
const savedTheme = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}
// テーマの切り替え
function toggleTheme() {
const isDark = document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', isDark ? 'dark' : 'light');
}
// ボタンにイベント設定
document.getElementById('theme-toggle').addEventListener('click', toggleTheme);
// 初期化(<head>内でも呼ぶとFOUC防止に効果的)
initTheme();
FLASHを防ぐ——FOUC対策
ページ読み込み時に一瞬ライトモードが表示されてからダークモードに切り替わる「FOUC(Flash of Unstyled Content)」を防ぐには、<head> 内で早期にクラスを設定します。
<head>
<meta charset="UTF-8">
<!-- ダークモード初期化スクリプト(他より先に実行) -->
<script>
(function() {
const theme = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (theme === 'dark' || (!theme && prefersDark)) {
document.documentElement.classList.add('dark');
}
})();
</script>
<!-- 以降のcssやJSはここに -->
</head>
カラーパレットの設計
ダークモードに対応したカラーパレットを tailwind.config.js で定義します。
module.exports = {
darkMode: 'class',
theme: {
extend: {
colors: {
// ライト/ダーク共通のセマンティックカラー
surface: {
DEFAULT: '#ffffff',
dark: '#1a1a2e',
},
'on-surface': {
DEFAULT: '#1c1c1c',
dark: '#e8e8e8',
},
primary: {
DEFAULT: '#d4b896',
dark: '#c9a97a',
},
},
},
},
}
コンポーネント全体での統一的な適用
<!-- カード コンポーネント例 -->
<div class="
bg-white dark:bg-gray-800
border border-gray-200 dark:border-gray-700
rounded-xl shadow-sm
p-6
transition-colors duration-200
">
<h3 class="text-gray-900 dark:text-gray-100 font-bold text-lg">
タイトル
</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm mt-2 leading-relaxed">
説明テキスト
</p>
<a href="#"
class="text-amber-700 dark:text-amber-400 hover:underline text-sm font-medium">
詳しく見る →
</a>
</div>
Alpine.jsとの組み合わせ
Alpine.jsを使うとよりリアクティブな実装ができます。
<div
x-data="{ dark: localStorage.getItem('theme') === 'dark' }"
x-init="$watch('dark', val => {
document.documentElement.classList.toggle('dark', val);
localStorage.setItem('theme', val ? 'dark' : 'light');
})"
:class="{ 'dark': dark }"
>
<button @click="dark = !dark" class="p-2 rounded">
<span x-show="!dark">🌙</span>
<span x-show="dark">☀️</span>
</button>
</div>
まとめ
Tailwind CSSのダークモードは dark: プレフィックスで直感的に実装でき、JavaScriptとlocalStorageを組み合わせることで、ユーザー設定を保持した切り替え機能を実現できます。弊社では新規プロジェクトでは標準的にダークモード対応を実施しています。
Webサイト・アプリのUI開発についてはお気軽にご相談ください。