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が付いた状態で表示されます。



JavaScriptで配列内から特定条件の要素を探す方法
ファビコンや各種アイコンの作成と設定方法
CSSで::placeholderにスタイルを設定する方法
npm install時に「cb() never called!」とエラーが表示されたときの解決法
無料版を使っている人は検討する価値あり!MAMP PRO 5で簡単にローカル開発環境を構築・管理する
Google Maps APIを使ってGoogle Mapsをウェブサイトに表示させる方法
Nuxt.jsでページを作成・追加する方法|Nuxt.jsの基本
Vue.jsを使う人が最低限導入しておきたいVisual Studio Codeの拡張機能
iTerm2を使いこなすために覚えておきたいショートカット集
Visual Studio CodeでMovable TypeのMTMLファイルを開く拡張機能「Movable Type Markup Language Syntax」
iTerm2で「Use System Window Restoration Setting」を設定しているとアラートが表示されて機能しない
Google Chromeのサイト内検索(カスタム検索)機能を別のプロファイルに移行する方法
iPadで入力モードを切り替えずに数字や記号をすばやく入力する方法
iPhoneやiPadでYouTubeの再生速度を3倍速や4倍速にする方法
Keynoteで有効にしているはずのフォントが表示されない現象
MacのKeynoteにハイライトされた状態でコードを貼り付ける方法
AirPodsで片耳を外しても再生が止まらないようにする方法
iTerm2でマウスやトラックパッドの操作を設定できる環境設定の「Pointer」タブ
DeepLで「インターネット接続に問題があります」と表示されて翻訳できないときに確認すること
Ulyssesの「第2のエディタ」表示を使って2つのシートを横並びに表示する
軽量で高速なターミナルエミュレーター「Ghostty」の設定方法
Eagleで実現するクリエイティブ素材の簡単管理
かゆいところに手が届く「Supercharge」でMac環境を便利にカスタマイズする
超軽量なコードエディタ 「Zed」をサブエディタとして活用する
Bartender 6で追加されたWidgets機能で自作メニューバーアイテムを簡単に作成する
Googleカレンダーを便利に活用するための小技集(祝日だけを表示・月末の繰り返しイベントを追加)
Obsidianを使った「自己流PKM」で行う知識トレーニング
テキストエディタ・ノートアプリ関連のショートカットキーをKeyboard Maestroで統一する
Path Finderを使ってキーボードだけでファイル操作する方法(応用編)