
以前、CSSでダークモードに対応する方法についてご紹介しましたが、JavaScript を使って動的に切り替えたい場合には少し工夫が必要です。この記事では、JavaScript を活用してライトモード・ダークモードを切り替える機能を実装する方法を解説します。
目次
CSS によるダークモード実装のおさらい
まずは、CSS だけでダークモードを実装する方法を確認しておきましょう。
@media (prefers-color-scheme: dark){} を使用する
以下のように@media (prefers-color-scheme: dark){}
を使用して CSS を記述すると、ユーザーのシステム設定(ブラウザなどの設定)に応じてダークモード用のスタイルが適用されます。
:root {
--text-color: black;
--body-bg-color: white;
}
@media (prefers-color-scheme: dark) {
:root {
--text-color: white;
--body-bg-color: black;
}
}
body {
color: var(--text-color);
background: var(--body-bg-color);
}
この例では、システム設定でダークモードが選択されている場合は CSS 変数の値が変わり、body
の文字色が白、背景色が黒に切り替わります。
light-dark() 関数を使用する
CSS の:root
疑似クラスでcolor-scheme
を設定したうえでlight-dark()
関数を使用すると、ユーザーのシステム設定に応じてダークモード用の値が適用されます。
:root {
color-scheme: light dark;
}
body {
color: light-dark(black, white);
background: light-dark(white, black);
}
JavaScript で切り替える際に必要な処理
JavaScript でライトモード・ダークモードを切り替える際、@media (prefers-color-scheme: dark){}
を使用しているかlight-dark()
関数を使用しているかによって必要な処理が変わってきます。
@media (prefers-color-scheme: dark){} を使用している場合
@media (prefers-color-scheme: dark){}
で指定されたスタイルは、JavaScript で動的に適用させることができません。そのため、JavaScript での切り替えを行うためには、メディアクエリの使用をやめ、通常のセレクタでスタイルを指定する形に変更する必要があります。
その際は、以下のようにモード判別のためのdata
属性をhtml
に付与し、それをセレクターに使用してスタイルを設定する方法が一般的です。
<html lang="ja" data-color-scheme="dark">
セレクターがhtml
に変更されるため、:root
疑似クラスで CSS 変数を定義している場合は、:root {}
の外に出す必要があります。
:root {
--text-color: black;
--body-bg-color: white;
}
/* @media (prefers-color-scheme: dark) → html[data-color-scheme="dark"] に変更 */
html[data-color-scheme="dark"] {
/* :root {} は外す */
--text-color: white;
--body-bg-color: black;
}
body {
color: var(--text-color);
background: var(--body-bg-color);
}
これにより、JavaScript でhtml
のdata
属性の変更を行うとライトモード・ダークモードの切り替えが可能になります。
light-dark() 関数を使用している場合
light-dark()
関数を使用している場合は、:root
疑似クラスに設定されているcolor-scheme
の値をlight
のみ、もしくはdark
のみに変更することでライトモード・ダークモードの切り替えが可能です。
このcolor-scheme
は、「このサイトではこのカラーのテーマを使用します」という宣言のようなもので、この値をどちらか片方のみにすることで、強制的にそのモードに切り替えることができます。
JavaScript によるダークモード切り替え機能の実装
さて、いよいよここからは、切り替え機能の実装について解説していきます。
切り替えボタンの設置
まずは、以下のように、ライトモード・ダークモードの切り替えボタンを HTML に設置します。
<div id="colorSchemeSelector">
<button name="light">ライトモード</button>
<button name="dark">ダークモード</button>
</div>
ボタン押下時の切り替え処理
次に、ボタンを押したときの処理を JavaScript で記述します。
window.addEventListener("DOMContentLoaded", function () {
// :root 疑似クラスを取得
const root = document.querySelector(":root");
// ボタン要素を取得
const colorSchemeButtons = document.querySelectorAll("#colorSchemeSelector button");
for(let i = 0; i < colorSchemeButtons.length; i++) {
// ボタン押下時の処理を設定
colorSchemeButtons[i].addEventListener("click", function() {
// 選択したモードの情報を localStorage に保存
localStorage.setItem('selectedColorScheme', this.name);
// color-scheme の値を書き換え
root.style.setProperty("color-scheme", this.name);
// html に data-color-scheme を設定
document.querySelector("html").dataset.colorScheme = this.name;
});
}
});
color-scheme
とdata
属性の書き換え以外に、選択したモードが次回以降のページ読み込み時にも反映されるようにするための情報をlocalStorage
に保存しています。
HTML の <head> 内にページ読み込み時の切り替えコードを記述
ページ読み込み時に、システム設定のprefers-color-scheme
やlocalStorage
の設定を反映するためのコードを<head>
内に記述します。
このコードは、システム設定のモードとサイト上で選択されたモードに差異があった場合のチラつきを防止するため、可能な限り<head>
内の上のほうに記述するのを推奨します。
<script>
(function() {
// :root 疑似クラスを取得
const root = document.querySelector(":root");
// localStorage に保存されたモードの情報を取得
const localSetting = localStorage.getItem("selectedColorScheme");
// ユーザーのシステム情報を取得
const systemPrefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
// localStorage に情報があればそちらを優先、なければシステム情報のモードを使用
const colorScheme = localSetting ? localSetting : (systemPrefersDark ? "dark" : "light");
// color-scheme の値を書き換え
root.style.setProperty("color-scheme", colorScheme);
// html に data-color-scheme を設定
document.querySelector("html").dataset.colorScheme = colorScheme;
})();
</script>
このコードにより、
localStorage
に保存された設定を最優先localStorage
に値がなければシステム設定のprefers-color-scheme
を使用する、といったロジックでモードが適用されます。
JavaScript によるダークモード切り替えのサンプル
以下は、JavaScript によるダークモード切り替えのサンプルです。ボタンを押すとライトモード・ダークモードが切り替わるのが確認できます。
See the Pen Untitled by YUTSUZO (@YUTSUZO) on CodePen.
終わりに
JavaScript を使用すれば、CSS のみでは出来なかったライトモード・ダークモードの切り替え機能を実現できます。ダークモード対応はユーザー体験を向上させる重要な要素です。ぜひ今回紹介した方法を活用し、ご自身のウェブサイトに実装してみてください!