2026年7月1日
2026年7月1日
WordPressでダークモードを実装する方法(CSS変数・切り替えボタン・設定の保存)
ダークモードは、OSやブラウザの「ダーク」の設定に合わせて、サイトを暗い背景・明るい文字で表示する仕組みです。プラグインを使わずに組み込む場合、次の3段階で作ると管理しやすくなります。
- 色をCSS変数(カスタムプロパティ)にまとめ、
prefers-color-schemeでOSの設定に合わせて切り替える - 切り替えボタンを置き、利用者が選んだ設定を
localStorageに保存する - ページを開いた瞬間に明るい画面が一瞬見える「ちらつき」を防ぐ
この記事のコードは、テーマを直接編集せず、子テーマに追加する前提です。子テーマの作り方はWordPressの子テーマを作成する方法を参照してください。
手順1: 色をCSS変数にまとめ、OSの設定に合わせる
子テーマのフォルダーに dark-mode.css を作ります。
/* ライト(既定) */
:root {
--site-bg: #ffffff;
--site-text: #1f2328;
--site-link: #0b57d0;
--site-border: #d0d7de;
color-scheme: light;
}
/* OSがダークで、利用者がライトを選んでいないとき */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--site-bg: #16181d;
--site-text: #e6e6e6;
--site-link: #8ab4f8;
--site-border: #3a3f47;
color-scheme: dark;
}
}
/* 利用者がダークを選んだとき */
:root[data-theme="dark"] {
--site-bg: #16181d;
--site-text: #e6e6e6;
--site-link: #8ab4f8;
--site-border: #3a3f47;
color-scheme: dark;
}
body {
background-color: var(--site-bg);
color: var(--site-text);
}
a {
color: var(--site-link);
}
考え方は次のとおりです。
- 何も選ばれていなければ、
prefers-color-scheme: darkでOSの設定に従います。 - 利用者がボタンで選ぶと、
<html>要素にdata-theme="dark"またはdata-theme="light"が付き、OSの設定より優先されます。 color-schemeを指定すると、フォームの入力欄やスクロールバーなど、ブラウザが描く部品も暗い配色になります。
テーマの見出し・ヘッダー・ボタンなどに色が直接書かれている場合は、その部分も var(--site-text) などに置き換えるか、ダーク用の指定を追加します。どこに色が指定されているかは、ブラウザの開発者ツールで要素を選ぶと確かめられます。
手順2: 切り替えボタンの JavaScript を書く
子テーマのフォルダーに dark-mode.js を作ります。
(function () {
var button = document.getElementById('theme-toggle');
if (!button) {
return;
}
var root = document.documentElement;
var media = window.matchMedia('(prefers-color-scheme: dark)');
function currentTheme() {
return root.getAttribute('data-theme') || (media.matches ? 'dark' : 'light');
}
function render() {
button.setAttribute('aria-pressed', currentTheme() === 'dark' ? 'true' : 'false');
}
button.addEventListener('click', function () {
var next = currentTheme() === 'dark' ? 'light' : 'dark';
root.setAttribute('data-theme', next);
try {
localStorage.setItem('theme', next);
} catch (e) {
// 保存できない環境では、このページの表示だけ切り替える
}
render();
});
// 選択していない利用者が OS の設定を変えたとき、ボタンの状態を合わせる
media.addEventListener('change', render);
render();
})();
ボタンの状態は aria-pressed で示します。スクリーンリーダーでも「押されている/押されていない」が伝わります。localStorage は、ブラウザの設定によっては使えないことがあるので、try で囲んでいます。
手順3: functions.php で読み込み、ボタンを出力する
子テーマの functions.php に追加します。
<?php
// ダークモード用の CSS と JavaScript を読み込む
add_action( 'wp_enqueue_scripts', function () {
$dir = get_stylesheet_directory();
$uri = get_stylesheet_directory_uri();
wp_enqueue_style(
'my-dark-mode',
$uri . '/dark-mode.css',
array(),
filemtime( $dir . '/dark-mode.css' )
);
wp_enqueue_script(
'my-dark-mode',
$uri . '/dark-mode.js',
array(),
filemtime( $dir . '/dark-mode.js' ),
true
);
} );
// 保存された設定を、描画の前に <html> に反映する(ちらつき対策)
add_action( 'wp_head', function () {
$js = "(function(){try{var t=localStorage.getItem('theme');"
. "if(t==='dark'||t==='light'){document.documentElement.setAttribute('data-theme',t);}"
. "}catch(e){}})();";
wp_print_inline_script_tag( $js );
}, 1 );
// 切り替えボタンを <body> の直後に出力する
add_action( 'wp_body_open', function () {
printf(
'<button type="button" id="theme-toggle" class="theme-toggle" aria-pressed="false">%s</button>',
esc_html__( 'ダークモード', 'my-child-theme' )
);
} );
ポイントは次のとおりです。
- 子テーマのファイルを指すときは
get_stylesheet_directory_uri()を使います。get_template_directory_uri()は親テーマのフォルダーを指すため、子テーマに置いたファイルが読み込まれません。 - バージョンに
filemtime()を渡すと、ファイルを更新したときにブラウザのキャッシュが切り替わります。 wp_headに優先度1で書いた短いスクリプトが、保存された設定を本文の描画より前に<html>に付けます。切り替えボタンの JavaScript はフッターで読み込まれるので、この処理を分けておかないと、ダークを選んだ利用者に明るい画面が一瞬見えます。wp_print_inline_script_tag()はWordPress 5.7で追加された関数です。wp_body_openは、テーマが<body>の直後でwp_body_open()を呼んでいる場合に動きます。2026年10月時点の公式テーマやブロックテーマは呼んでいますが、古いテーマで呼ばれていない場合は、wp_footerで出力して CSS で位置を決めます。
ボタンの見た目は dark-mode.css に追加します。画面の隅に固定する例です。
.theme-toggle {
position: fixed;
right: 16px;
bottom: 16px;
z-index: 1000;
padding: 8px 14px;
border: 1px solid var(--site-border);
border-radius: 999px;
background: var(--site-bg);
color: var(--site-text);
cursor: pointer;
}
.theme-toggle:focus-visible {
outline: 2px solid var(--site-link);
outline-offset: 2px;
}
ブロックテーマの場合
Twenty Twenty-Four や Twenty Twenty-Five などのブロックテーマでは、配色が theme.json のパレットで決まり、--wp--preset--color--スラッグ名 というCSS変数として出力されます。手順1の --site-bg などの代わりに、これらの変数をダーク用の値で上書きします。
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--wp--preset--color--base: #16181d;
--wp--preset--color--contrast: #e6e6e6;
}
}
:root[data-theme="dark"] {
--wp--preset--color--base: #16181d;
--wp--preset--color--contrast: #e6e6e6;
}
base(背景)と contrast(文字)は上の2つの公式テーマで使われているスラッグです。テーマによってスラッグ名や色の数が違うので、テーマの theme.json の settings.color.palette を開いて、使われているスラッグを確かめてから書きます。
動作の確かめ方
- OSの設定に従うか: Chromeの開発者ツールで「レンダリング」(Rendering)パネルを開き、
prefers-color-schemeのエミュレートでdarkとlightを切り替えます。 - ボタンで切り替わるか: ボタンを押して配色が変わり、ページを再読み込みしても選んだ配色のままかを確かめます。
- ちらつかないか: ダークを選んだ状態で別のページに移動し、明るい画面が一瞬見えないかを確かめます。
- 読みやすさ: 本文・リンク・ボタンの文字と背景のコントラストを確かめます。WCAG 2.2 では、通常の大きさの文字で4.5:1以上が基準です。開発者ツールで要素を選ぶと、コントラスト比が表示されます。
注意点
- 黒い線で描かれたロゴや図、透過PNGは、暗い背景で見えにくくなります。ロゴはダーク用の画像を用意するか、背景色を付けて表示します。
- 埋め込みの地図・動画・広告などは、サイトのCSSでは色が変わりません。
- キャッシュ系プラグインやCSSの結合・圧縮を使っている場合は、ファイルを変更した後にキャッシュを削除します。
- 切り替えの機能だけが欲しく、コードを管理したくない場合は、ダークモード用のプラグインを使う方法もあります。プラグインの多くは自動で色を反転させるため、画像やテーマによっては不自然になることがあり、表示を確かめてから採用します。
まとめ
ダークモードは、色をCSS変数にまとめ、prefers-color-scheme と data-theme 属性で切り替える形にすると、OSの設定と利用者の選択の両方に対応できます。子テーマでは get_stylesheet_directory_uri() でファイルを読み込み、保存した設定は wp_head の早い段階で <html> に反映して、表示時のちらつきを防ぎます。ブロックテーマでは --wp--preset--color-- の変数を上書きします。切り替えボタンの作り方をさらに詳しく知りたい場合はWordPressにダークモードの切り替えボタンを付ける方法も参照してください。