メインコンテンツへスキップ
見出し画像

【CSS_96】 ダークモードの切り替え設計

    ダークモードの切り替え


    はじめに:なぜダークモードが必要なのか?

    現代のWebアプリケーションやサイトでは、「ダークモード」が標準の機能になりつつあります。
    単なる流行ではなく、ユーザー体験(UX)・可読性・バッテリー効率といった観点での実用的なメリットが豊富にあります。


    ダークモード設計の基本原理

    2つのモード

    • ライトモード(Light Mode):背景が明るく、黒文字中心

    • ダークモード(Dark Mode):背景が暗く、白文字中心

    切り替え方法の種類

    OS設定連動(prefers-color-scheme)
     ユーザーのOSの設定に従う
    アプリ内トグル(手動切替)
     ボタンやスイッチで明示的に切り替え
    ローカル保存との併用
     初回はOSに従い、その後は選択を記憶


    実装ステップ全体像

    1. CSS設計(変数設計)

    2. メディアクエリによるOS連動

    3. ユーザー手動切替の実装

    4. 状態保存(localStorage)

    5. フレームワーク(React等)対応

    6. アクセシビリティ対応

    7. 切替時のトランジション


    1. CSS設計:カスタムプロパティ(CSS変数)

    色の定義を変数化

    :root {
      --bg-color: #ffffff ;
      --text-color: #000000 ;
    }
    
    [data-theme='dark'] {
      --bg-color: #121212 ;
      --text-color: #f1f1f1 ;
    }

    実際のスタイルで使用

    body {
      background-color: var(--bg-color);
      color: var(--text-color);
    }

    2. OSのダークモード検知

    ◉ メディアクエリ prefers-color-scheme

    @media (prefers-color-scheme: dark) {
      :root {
        --bg-color: #121212 ;
        --text-color: #f1f1f1 ;
      }
    }

    これは自動でOSに従って切り替わるパターンです。
    ただし、ユーザーの明示的な選択を上書きすることはしません。


    3. ユーザー手動切り替え(JavaScript)

    ◉ HTML構造(例)

    <button id="toggle-theme">テーマ切替</button>

    ◉ JavaScriptで切替制御

    const toggle = document.getElementById('toggle-theme');
    toggle.addEventListener('click', () => {
      const current = document.documentElement.getAttribute('data-theme');
      const next = current === 'dark' ? 'light' : 'dark';
      document.documentElement.setAttribute('data-theme', next);
      localStorage.setItem('theme', next);
    });

    4. 状態の永続化(localStorage)

    ◉ 初期読み込み時に設定を反映

    const savedTheme = localStorage.getItem('theme');
    if (savedTheme) {
      document.documentElement.setAttribute('data-theme', savedTheme);
    } else {
      const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
      document.documentElement.setAttribute('data-theme', prefersDark ? 'dark' : 'light');
    }

    5. フレームワーク対応:Reactでの実装例

    ◉ React Hookで管理

    import { useEffect, useState } from 'react';
    
    export const useDarkMode = () => {
      const [theme, setTheme] = useState<'light' | 'dark'>(() => {
        const saved = localStorage.getItem('theme');
        if (saved) return saved as 'light' | 'dark';
        return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
      });
    
      useEffect(() => {
        document.documentElement.setAttribute('data-theme', theme);
        localStorage.setItem('theme', theme);
      }, [theme]);
    
      const toggleTheme = () => {
        setTheme((prev) => (prev === 'dark' ? 'light' : 'dark'));
      };
    
      return { theme, toggleTheme };
    };

    ◉ 使用例

    const App = () => {
      const { theme, toggleTheme } = useDarkMode();
    
      return (
        <div>
          <button onClick={toggleTheme}>
            現在のテーマ: {theme}
          </button>
        </div>
      );
    };

    6. トランジションでUX向上

    body {
      transition: background-color 0.3s ease, color 0.3s ease;
    }

    注意:トランジション適用前にDOMに即座にテーマ属性が付くようにすること。


    7. アクセシビリティと視認性の注意点

    コントラスト比
     WCAG2.1で4.5:1以上推奨(文字と背景)
    フォーカス状態
     ダーク背景でも outline を明確に
    スクロールバー
     ブラウザ依存で見えにくくなる場合あり
    色依存のUI
     意味を色だけで伝えない工夫(アイコン等併用)


    色の設計ヒント

    背景
     ライトモード: #ffffff
     ダークモード: #121212
    テキスト
     ライトモード: #000000
     ダークモード: #f1f1f1
    アクティブボタン
     ライトモード:#007BFF
     ダークモード: #90CAF9
    ボーダー
     ライトモード:#e0e0e0
     ダークモード: #333333
    影
     ライトモード:rgba(0,0,0,0.1)
     ダークモード: rgba(0,0,0,0.5)


    よくあるミスと対策

    CSS変数を使っていない
     管理が地獄に
     → 変数ベースの設計に徹する
    切り替えが一瞬で反映されず白フラッシュ
     初期テーマ設定が遅い
     → <script>で先にdata-theme設定
    トグル切替が効かない
     localStorageとUIが連動していない
     → Hook or Contextで状態一元化


    高度な応用

    Tailwind CSSでのダークモード対応(class戦略)

    // tailwind.config.js
    module.exports = {
      darkMode: 'class', // または 'media'
    }
    <body class="dark:bg-black dark:text-white bg-white text-black">

    切り替えは以下のように制御

    document.documentElement.classList.toggle('dark');

    まとめ:良いダークモードとは?

    • 可読性が高い(コントラスト重視)

    • パフォーマンス低下がない

    • CSS変数で柔軟に拡張可能

    • ユーザーに選択権を与える

    • アクセシブルで視覚的にも一貫



     
     
    フロントエンド、バックエンドのエンジニアをやっております。 読むだけで複雑だったはずの技術が、すっと腑に落ちる。その静かな感動を届けたい。

    あなたへのおすすめ