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



Visual Studio Codeで「.html」拡張子以外のファイルでもEmmetを使えるようにする
属性・Class・IdなどHTMLタグの細かい部分を見ていこう!!
iOS Safariでinputタグにフォーカスを合わせると、自動で画面が拡大してしまう原因と解決方法
SourceTreeで環境設定の「カスタムアクション」「アップデート」「高度な設定」が選択できない
iOS Safariで指定したフォントサイズにならない場合の対処法
iOS Safariで文章の最後の1文字だけ改行されてしまう現象の対処法
GUIコンパイラのPreprosを使ってSassのコンパイルを行う
CSSでclassがついていないタグにだけスタイルを当てる方法
Local by Flywheelの「Starting Local Machine…」画面から進まないときに試すこと
Visual Studio CodeをMarkdownエディターとして使用する
iTerm2で「Use System Window Restoration Setting」を設定しているとアラートが表示されて機能しない
Google Chromeのサイト内検索(カスタム検索)機能を別のプロファイルに移行する方法
iPadで入力モードを切り替えずに数字や記号をすばやく入力する方法
iPhoneやiPadでYouTubeの再生速度を3倍速や4倍速にする方法
Keynoteで有効にしているはずのフォントが表示されない現象
MacのKeynoteにハイライトされた状態でコードを貼り付ける方法
AirPodsで片耳を外しても再生が止まらないようにする方法
iTerm2でマウスやトラックパッドの操作を設定できる環境設定の「Pointer」タブ
DeepLで「インターネット接続に問題があります」と表示されて翻訳できないときに確認すること
Ulyssesの「第2のエディタ」表示を使って2つのシートを横並びに表示する
操作に没頭できる!Firefox版 Arcのようなブラウザ「Zen Browser」
chezmoi(シェモア)で始めるdotfiles管理
GitHubの通知を見逃さない!通知に特化したアプリ「Gitify」
Keyboard Maestroの変数基礎
Neovimを使い始める最初の一歩として便利な「LazyVim」
ウェブサイトをmacOSアプリとしてラッピングする「Unite Pro」
Keyboard Maestroの「Macro Debugger」で複雑なマクロのデバッグを行う方法
無料版でも高機能なランチャーアプリ「Raycast」の基本機能と環境設定
OnyXでターミナルを使わずにmacOSの詳細設定を行う
軽量で高速なターミナルエミュレーター「Ghostty」の設定方法