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