ダークモード切り替えボタンの実装方法|JS & CSS Dark Mode Toggle Guide

ダークモード切り替え デザイン見本

CSS カスタムプロパティ(変数)と JavaScript を組み合わせ、ボタンクリックでライト/ダークモードを切り替える実装デモです。OS設定への自動対応と localStorage による設定の保持も含めたコードを掲載しています。

① CSS カスタムプロパティ — テーマカラーを変数で一元管理

–bg-color: #f8fafc

–text-color: #1e293b

–border-color: #e2e8f0

My Page

本文タイトル

CSS カスタムプロパティを使うと、.dark-mode クラスの付け外しだけで全体の配色が切り替わります。

CSS
:root {
  --bg-color: #f8fafc;
  --text-color: #1e293b;
  --border-color: #e2e8f0;
}

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

body.dark-mode {
  --bg-color: #0f172a;
  --text-color: #e2e8f0;
  --border-color: #334155;
}
:root とカスタムプロパティ(CSS変数)

:root 疑似クラスは HTML 要素を指し、ここで定義した --変数名: 値 はドキュメント全体で var(--変数名) として参照できます。body.dark-mode で同じ変数を上書きするだけで配色が一括切り替わるため、テーマ管理が格段にシンプルになります。カラーパレットを後から変更する際も、変数定義の箇所だけ修正すれば全体に反映されます。

② dark-mode クラスの切り替え — ボタンでテーマを変える

タイトル

ボタンをクリックするとライト/ダークモードが切り替わります。

About

CSS変数と JavaScript を組み合わせた実装例です。

HTML
<button id="mode-toggle">ダークモードに切り替え</button>

<div id="container">
  <p>サンプルテキスト</p>
</div>
CSS
:root {
  --bg-color: #f8fafc;
  --text-color: #1e293b;
  --card-bg: #ffffff;
  --border-color: #e2e8f0;
}

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

body.dark-mode {
  --bg-color: #0f172a;
  --text-color: #e2e8f0;
  --card-bg: #1e293b;
  --border-color: #334155;
}

#mode-toggle {
  padding: 8px 18px;
  border: 1px solid #2563eb;
  border-radius: 6px;
  background: #3b82f6;
  color: #fff;
  cursor: pointer;
  font-size: 14px;
  transition: background 0.3s;
}

#container {
  margin-top: 16px;
  padding: 20px;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: 10px;
  transition: background 0.3s, border-color 0.3s;
}
JS
(function() {
  var toggleBtn = document.getElementById('mode-toggle');
  if (!toggleBtn) return;

  function applyTheme(theme) {
    if (theme === 'dark') {
      document.body.className = 'dark-mode';
      toggleBtn.textContent = 'ライトモードに切り替え';
    } else {
      document.body.className = '';
      toggleBtn.textContent = 'ダークモードに切り替え';
    }
  }

  toggleBtn.addEventListener('click', function() {
    var nowDark = document.body.className.indexOf('dark-mode') !== -1;
    applyTheme(nowDark ? 'light' : 'dark');
  });
})();
applyTheme() で className とボタンテキストを同時に更新

現在のモードは body.className.indexOf('dark-mode') !== -1 で判定します。applyTheme() 関数にまとめることで、初期化時とクリック時の両方から同じロジックを呼び出せます。ボタンのテキストも同関数内で更新するため、状態と表示が常に一致します。body.className = 'dark-mode' のように直接代入する方法は、既存クラスとの干渉を避けたい場合は classList.add() の利用も検討してください。

③ localStorage + prefers-color-scheme — 設定の保持と OS 連動

状態パネル

OS 設定:

localStorage:

現在のテーマ:

設定はブラウザに保存されます。ページを再読み込みしてもテーマが維持されます。

HTML
<button id="mode-toggle">ダークモードに切り替え</button>

<div id="container">
  <p>サンプルテキスト</p>
</div>
CSS
:root {
  --bg-color: #f8fafc;
  --text-color: #1e293b;
  --card-bg: #ffffff;
  --border-color: #e2e8f0;
}

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

body.dark-mode {
  --bg-color: #0f172a;
  --text-color: #e2e8f0;
  --card-bg: #1e293b;
  --border-color: #334155;
}

#mode-toggle {
  padding: 8px 18px;
  border: 1px solid #2563eb;
  border-radius: 6px;
  background: #3b82f6;
  color: #fff;
  cursor: pointer;
  font-size: 14px;
  transition: background 0.3s;
}

#container {
  margin-top: 16px;
  padding: 20px;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: 10px;
  transition: background 0.3s, border-color 0.3s;
}
JS
(function() {
  var toggleBtn = document.getElementById('mode-toggle');
  if (!toggleBtn) return;

  var storedTheme = localStorage.getItem('theme-pref');
  var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;

  function applyTheme(theme) {
    if (theme === 'dark') {
      document.body.className = 'dark-mode';
      toggleBtn.textContent = 'ライトモードに切り替え';
    } else {
      document.body.className = '';
      toggleBtn.textContent = 'ダークモードに切り替え';
    }
  }

  if (storedTheme) {
    applyTheme(storedTheme);
  } else if (prefersDark) {
    applyTheme('dark');
  }

  toggleBtn.addEventListener('click', function() {
    var nowDark = document.body.className.indexOf('dark-mode') !== -1;
    var nextTheme = nowDark ? 'light' : 'dark';
    applyTheme(nextTheme);
    localStorage.setItem('theme-pref', nextTheme);
  });
})();
localStorage.getItem / setItem でテーマを保存・復元

ページ読み込み時に localStorage.getItem('theme-pref') で保存済みテーマを取得します。未保存の場合は window.matchMedia('(prefers-color-scheme: dark)').matches でOSのダークモード設定を検出して自動適用します。ボタンクリック時は localStorage.setItem('theme-pref', nextTheme) で選択を保存するため、次回アクセス時も同じテーマが維持されます。

@media (prefers-color-scheme: dark) と JS 切り替えは併用しない

@media (prefers-color-scheme: dark):root にダーク変数を設定すると、JS で body.dark-mode クラスを外してもメディアクエリが常に上書きするため、ライトモードに戻せなくなります。JS でクラスを切り替える方式(このセクションのコード)と、CSS メディアクエリのみの方式(JS なし)は、どちらか一方だけを使ってください。OS 連動は JS の matchMedia 側で行うため、CSS メディアクエリは不要です。


当サイトで公開しているWebデザインやUIの実装例は、一覧として以下記事に纏めています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次