js-cookieでウェブサイトのダークモード表示設定をユーザーごとに保存しておく方法

少し前にブログをリニューアルして、そのときに一緒にダークモードの対応を行いました。
ただ、人によっては「システム環境設定に依存しないで、常にダークモードの方がいい!」人や「逆にライトモードの方が見やすい!」という人もいると思い、個別に設定できるように変更してみました。
今後デザインは変えていく予定ですが、メニュー右上の「表示設定」をクリックすると設定モーダルが表示されます。

このラジオボタンを選択すると、それぞれのモードに固定されます。
- ライト
- ダーク
- ナイト
- システム設定に合わせる(デフォルト)
ちなみに「ライトモード」と「ダークモード」以外に「ナイトモード」という表示も追加していて、これは深夜暗い部屋でも見やすいように、色を全体的に暗くして画像の輝度も下がります。
今回はこれの実装方法についてまとめておきます。
ダークモード自体の実装方法は有名ですが、それを保存する方法についてはあまり見かけなかったので、ぜひ参考にしてください。
ダークモードの対応
そもそもまずはダークモードの対応が必要です。
CSS変数を利用して、ライトモード(通常)時と@media (prefers-color-scheme: dark) {}を使って、ダークモード時の色を設定します。
:root{
--c-primary: #0076b5;
--c-secondary: #17C2C7;
--c-background-base: #F7F9FB;
--c-background-primary: #FFF;
--c-background-secondary: #F0F2F5;
--c-text-base: #555;
--c-text-lighter: #676767;
--c-text-link: #0076b5;
}
@media (prefers-color-scheme: dark) {
:root{
--c-primary: #EBCB1A;
--c-secondary: #FF178D;
--c-background-base: #2B2B2B;
--c-background-primary: #313131;
--c-background-secondary: #242424;
--c-text-base: #EAEAEA;
--c-text-lighter: #B7B7B7;
--c-text-link: #0076b5;
}
}これでライトモードとダークモードの指定はできましたが、このままだとメディアクエリでのみの設定になるので、bodyに特定classが付いたときにも変数が変わるようにしておきます。
body.dark-mode{
--c-primary: #0076b5;
--c-secondary: #17C2C7;
--c-background-base: #F7F9FB;
--c-background-primary: #FFF;
--c-background-secondary: #F0F2F5;
--c-text-base: #555;
--c-text-lighter: #676767;
--c-text-link: #0076b5;
}js-cookieの導入
js-cookieを使うと、JavaScriptでCookieの登録や取得が簡単にできます。こちらから読み込みます。
js-cookieでCookieの登録
Cookieを登録したい場合はCookies.set('Cookie名', 値);で登録できます。
Cookies.set('darkmode', darkModeVal);Cookieを取得したい場合はCookies.get('Cookie名');で取得できます。
Cookies.get('darkmode');あとはラジオボタンでどこがチェックされているのかを判定するのと、判定に応じてbodyにclassを追加するだけです。
let getDarkModeVal = function () {
let radios = document.getElementsByName('darkmode');
for (let i = 0; i < radios.length; i++) {
if (radios[i].checked) {
return radios[i].id;
}
}
}
let setDarkModeVal = () => {
let darkModeVal = getDarkModeVal();
switch (darkModeVal) {
case 'light':
document.body.classList.add("light-theme");
document.body.classList.remove("dark-theme");
document.body.classList.remove("night-theme");
break;
case 'dark':
document.body.classList.remove("light-theme");
document.body.classList.add("dark-theme");
document.body.classList.remove("night-theme");
break;
case 'night':
document.body.classList.remove("light-theme");
document.body.classList.remove("dark-theme");
document.body.classList.add("night-theme");
break;
default:
document.body.classList.remove("light-theme");
document.body.classList.remove("dark-theme");
document.body.classList.remove("night-theme");
break;
}
Cookies.set('darkmode', darkModeVal);
}
const darkMode = Cookies.get('darkmode');
if (darkMode) {
document.getElementById(darkMode).checked = true;
} else {
document.getElementById('system').checked = true;
}
// チェックした時の挙動
let radios = document.getElementsByName('darkmode');
for (let i = 0; i < radios.length; i++) {
radios[i].addEventListener('change', () => {
setDarkModeVal();
});
}PHPでCookieに合わせてclassを追加する
いまのままだと、ページが表示された後にJavaScriptが読み込まれてclassが付くまでの間はライトモードが表示されてしまいます。
一瞬ライトモードが表示されて、そのあとダークモードになったりするのはむしろ目がチカチカしてしまうので、Cookieが設定されてある場合はPHPで最初からclassを付けておくようにしましょう。
PHPでやることはCookieの取得のみで、isset( $_COOKIE['Cookie名'] )で取得ができるので、取得したあとは条件分岐でclassの中身を設定します。
<?php if ( isset( $_COOKIE['darkmode'] )){
if($_COOKIE['darkmode'] == 'light'){
$darkModeClass = 'light-theme';
}elseif($_COOKIE['darkmode'] == 'dark'){
$darkModeClass = 'dark-theme';
}elseif($_COOKIE['darkmode'] == 'night'){
$darkModeClass = 'night-theme';
}
}?>
<body class="<?php echo $darkModeClass ?>">これで、ダークモードのCookieが設定されてある場合は最初からダークモードのclassが付いた状態で表示されます。



CSSで1行で簡単にスムーススクロールを実装できる「scroll-behavior」プロパティ
Dart Sassの変数の基本的な使い方|Dart Sass入門
JavaScriptで日付をコピーして計算すると、コピー元の日付も変わってしまう場合の対処法
PS Auto Sitemapを使って自分のブログのサイトマップを作成する
コーディングで「スペース」と「タブ」のどちらを使えばいいのか?
Facebookでシェアした記事の画像反映ができていない時の修正方法
「DevTools z-index」でz-indexがかかっている要素をChrome開発者ツールに一覧表示させる
様々な作業を自動化するgulpの基礎と導入方法
HTML・CSSでWebサイト制作を行う際に必要なツール
EJSのincludeで別ファイルを読み込むときの画像パスを指定する方法
iTerm2で「Use System Window Restoration Setting」を設定しているとアラートが表示されて機能しない
Google Chromeのサイト内検索(カスタム検索)機能を別のプロファイルに移行する方法
iPadで入力モードを切り替えずに数字や記号をすばやく入力する方法
iPhoneやiPadでYouTubeの再生速度を3倍速や4倍速にする方法
Keynoteで有効にしているはずのフォントが表示されない現象
MacのKeynoteにハイライトされた状態でコードを貼り付ける方法
AirPodsで片耳を外しても再生が止まらないようにする方法
iTerm2でマウスやトラックパッドの操作を設定できる環境設定の「Pointer」タブ
DeepLで「インターネット接続に問題があります」と表示されて翻訳できないときに確認すること
Ulyssesの「第2のエディタ」表示を使って2つのシートを横並びに表示する
1つのノートアプリにすべて集約するのをやめた理由|2025年時点のノートアプリの使い分け
Notionログイン時の「マジックリンク」「ログインコード」をやめて普通のパスワードを使う
AlfredでNotion内の検索ができるようになるワークフロー「Notion Search」
Gitで1行しか変更していないはずのに全行変更した判定になってしまう
Macでアプリごとに音量を調節できるアプリ「Background Music」
Macのターミナルでパスワード付きのZIPファイルを作成する方法
MacBook Proでディスプレイのサイズ調整をして作業スペースを広げる
SteerMouseの「自動移動」機能で保存ダイアログが表示されたら自動でデフォルトボタンへカーソルを移動させる
iPhoneでタッチが一切効かなくなった場合に強制再起動する方法