2026年5月20日

2026年5月20日

WordPressにダークモードを実装する方法

はじめに

ダークモードはOSの設定に自動追従する方法と、ユーザーがボタンで切り替える方法の2種類があります。WordPressでは CSS変数(カスタムプロパティ)と prefers-color-scheme メディアクエリを組み合わせるのが最もメンテナブルな実装です。

症状・原因

  • OS設定に合わせてダークモードを自動適用したい
  • ユーザーがボタンで手動切り替えできるようにしたい
  • ダークモード時に画像が明るすぎる
  • ユーザーの選択をページをまたいで保持したい

解決手順

ステップ1:CSS変数でカラーパレットを定義する

/* style.css */

/* ライトモード(デフォルト) */
:root {
    --color-bg: #ffffff;
    --color-bg-secondary: #f6f7f7;
    --color-text: #1d2327;
    --color-text-muted: #50575e;
    --color-border: #dcdcdc;
    --color-primary: #2271b1;
    --color-primary-hover: #135e96;
    --color-shadow: rgba(0, 0, 0, 0.1);
}

/* ダークモード(OS設定に自動追従) */
@media (prefers-color-scheme: dark) {
    :root {
        --color-bg: #1d2327;
        --color-bg-secondary: #2c3338;
        --color-text: #f0f0f1;
        --color-text-muted: #a7aaad;
        --color-border: #3c434a;
        --color-primary: #72aee6;
        --color-primary-hover: #93c5fd;
        --color-shadow: rgba(0, 0, 0, 0.4);
    }
}

/* 手動ダークモード(data属性で制御) */
[data-theme="dark"] {
    --color-bg: #1d2327;
    --color-bg-secondary: #2c3338;
    --color-text: #f0f0f1;
    --color-text-muted: #a7aaad;
    --color-border: #3c434a;
    --color-primary: #72aee6;
    --color-primary-hover: #93c5fd;
    --color-shadow: rgba(0, 0, 0, 0.4);
}

[data-theme="light"] {
    --color-bg: #ffffff;
    --color-bg-secondary: #f6f7f7;
    --color-text: #1d2327;
    --color-text-muted: #50575e;
    --color-border: #dcdcdc;
    --color-primary: #2271b1;
    --color-primary-hover: #135e96;
}

ステップ2:CSS変数をスタイルに適用する

body {
    background-color: var(--color-bg);
    color: var(--color-text);
    transition: background-color 0.3s ease, color 0.3s ease;
}

a { color: var(--color-primary); }
a:hover { color: var(--color-primary-hover); }

.site-header {
    background: var(--color-bg-secondary);
    border-bottom: 1px solid var(--color-border);
}

/* ダークモード時に画像を少し暗くする */
@media (prefers-color-scheme: dark) {
    img:not([src*=".svg"]) {
        filter: brightness(0.9);
    }
}
[data-theme="dark"] img:not([src*=".svg"]) {
    filter: brightness(0.9);
}

ステップ3:トグルボタンを追加する(PHP)

// header.php
function mytheme_dark_mode_toggle(): void {
    ?>
    <button
        id="dark-mode-toggle"
        class="dark-mode-toggle"
        aria-label="ダークモードを切り替え"
        type="button"
    >
        <span class="icon-light" aria-hidden="true">☀️</span>
        <span class="icon-dark" aria-hidden="true">🌙</span>
    </button>
    <?php
}

ステップ4:JavaScriptで切り替えと保存を実装する

// js/dark-mode.js
(function () {
    const STORAGE_KEY = 'theme-preference';
    const root = document.documentElement;
    const toggle = document.getElementById('dark-mode-toggle');

    // 保存済み設定またはOS設定を取得
    function getTheme() {
        const saved = localStorage.getItem(STORAGE_KEY);
        if (saved) return saved;
        return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
    }

    // テーマを適用
    function applyTheme(theme) {
        root.dataset.theme = theme;
        if (toggle) {
            toggle.setAttribute('aria-pressed', theme === 'dark' ? 'true' : 'false');
        }
    }

    // 初期化
    applyTheme(getTheme());

    // ボタンクリック
    if (toggle) {
        toggle.addEventListener('click', () => {
            const current = root.dataset.theme;
            const next = current === 'dark' ? 'light' : 'dark';
            localStorage.setItem(STORAGE_KEY, next);
            applyTheme(next);
        });
    }

    // OS設定変更を検知
    window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
        if (!localStorage.getItem(STORAGE_KEY)) {
            applyTheme(e.matches ? 'dark' : 'light');
        }
    });
})();
// functions.php
function mytheme_enqueue_dark_mode(): void {
    wp_enqueue_script(
        'mytheme-dark-mode',
        get_template_directory_uri() . '/js/dark-mode.js',
        [],
        '1.0.0',
        false // HEADで読み込み(フラッシュ防止)
    );
}
add_action('wp_enqueue_scripts', 'mytheme_enqueue_dark_mode');

注意事項

  • スクリプトを head で読み込まないと、ページ読み込み時にライトモードが一瞬点滅する「フラッシュ(FOIT)」が発生します
  • transition プロパティで色変化をアニメーションすると、スクリプト読み込み前の初期表示でも適用されるため、フラッシュがやや目立つ場合があります
  • Gutenbergブロックエディタ内でもダークモードを有効にするには enqueue_block_editor_assets でスタイルを追加する必要があります

まとめ

CSS変数でカラーパレットを一元管理し、@media (prefers-color-scheme: dark) でOS追従、[data-theme="dark"] でユーザー手動切り替えを実現します。選択は localStorage に保存し、スクリプトは に配置してフラッシュを防ぎます。

お気軽にご相談ください

お見積りへ お問い合わせへ