We Blog Weblog

ダークモード

Web

2022年1月25日

みなさんこんにちは。
ケミストのWeb担当みやのです。

「Web」記事では、これまでに得たWebに関する知識を記録として残していきたいと思います。

さて今回は「ダークモード」を実装した時の様子をお伝えします。

参考:Webクリエイターボックス|Webサイトをダークモードに対応させよう

ダークモードとは

ダークモード(ダークテーマ)とは、黒背景・白文字を基調とした画面の配色のことです。

iPhoneやAndroidの端末で設定したり、ソフトやアプリで設定したりできます。

ダークモードのメリットは、

・目に優しい

・見やすい

・有機ELで消費電力が40%減る

・ブルーライトが減る

・集中力が高まる

だそうです(ホンマかいな)

端末の設定に対応

CSSで以下の設定をします。

:root {
  --main-text: #333;
  --main-bg: #fff;
}

@media (prefers-color-scheme: dark) {
  :root {
    --main-text: #ddd;
    --main-bg: #000;
  }
}

body {
  color: var(--main-text);
  background-color: var(--main-bg);
  transition: .3s;
}

通常時は
文字色 背景色

ダークモードでは
文字色 背景色
になります。

--〇〇 はCSS変数(カスタムプロパティ)というらしいです。勉強になります!

これでだいたいOKなのですが、気になる部分には以下のCSSを追加します。

color: inherit;
background-color: transparent;

inheritは「継承」という意味で、親要素の属性値を引き継ぐ効果があります。

transparentは「透明」を意味します。

切り替えスイッチ実装

サイト上でダークモードのオンオフができるようにしたいと思います。

まずはCSSでライトモード、ダークモードのスタイルを設定します。

.light-theme {
  background: #fff;
  color: #333;
}

.dark-theme {
  background: #000;
  color: #ddd
}

JavaScriptで、ダークモードならdark-theme、そうでないならlight-themeを<body>に対して付与します。

const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const darkModeOn = darkModeMediaQuery.matches;
 
darkModeMediaQuery.addListener((e) => {
  const darkModeOn = e.matches;
    if (darkModeOn) {
        document.body.classList.remove('light-theme');
        document.body.classList.add('dark-theme');
    } else {
        document.body.classList.remove('dark-theme');
        document.body.classList.add('light-theme');
    }
}); 

constが定数で、ifとelseが命令文です。たぶん。


前回作ったトグルスイッチを使います。

<div class="toggle_switch">
  <input id="btn-mode" type="checkbox" value=""><label for="btn-mode"></label>
</div>

トグルスイッチにbtn-modeというIDを設定します。


const btn = document.querySelector("#btn-mode");
 
btn.addEventListener("change", () => {
  if (btn.checked == true) {
    document.body.classList.remove("light-theme");
    document.body.classList.add("dark-theme");
  } else {
    document.body.classList.remove("dark-theme");
    document.body.classList.add("light-theme");
  }
});
DARK MODE

チェックボックスにチェックが入っていれば(=スイッチがオンならば)dark-theme、そうでないならlight-themeが<body>に対して付与されます。

これでパウっと解決!ワンダフル!のはずでしたが...

誤算

トグルスイッチを左のメニューの下に設置すると、なぜか勝手にオンになってしまいます。
スイッチの見た目だけの問題なので、端末でダークモードを設定していないなら画面はライトモードです。つまり、

①スイッチはオンだが画面はライトモード

②スイッチオフ→ライトモードのまま

③再度スイッチオン→ダークモードになる

という状況になってしまいました。
checkedを入れなければ、初期状態ではオフのはずなのに...

なにジョジョ?
トグルスイッチが
オフにならない?

ジョジョ それは
無理矢理オフにしようと
するからだよ

逆に考えるんだ
「オンのままでいいさ」と
考えるんだ

と、ジョースター卿もおっしゃっていました。何とかしましょう。

解決法その①

このスイッチは「ライトモードのオンオフスイッチ」だと思うことにします。
ただ、見た目的には「ダークモードのオンオフスイッチ」にしたいので、オンとオフの見た目を逆にしてごまかします。

さっきのJavaScriptのifとelseの内容を逆にします。

btn.addEventListener("change", () => {
  if (btn.checked == true) {
    document.body.classList.remove("dark-theme");
    document.body.classList.add("light-theme");
  } else {    
    document.body.classList.remove("light-theme");
    document.body.classList.add("dark-theme");
  }
});

チェックされていればlight-theme、そうでなければdark-themeが適用されます。


トグルスイッチのオンとオフの見た目を入れ替えます。

.toggle_switch > label {
  background-color: #2dcb45;
}

.toggle_switch > input:checked + label {
  background-color: #2b2a2f;
}

.toggle_switch > label::before {
  left: 0.9em;
}

.toggle_switch > input:checked + label::before {
  left: 0.1em;
}

オフの見た目がオンの見た目がになります(ややこしい)

一応これで意図した挙動になりましたが、ページ読み込み時に一瞬スイッチがオン→オフ(内部的にはオフ→オン)になるのがモヤっとします。

解決法その②

メニューにトグルスイッチを複数設置した場合はどうなるかというと、勝手にオンになるのは最初の1つだけと判明しました。マジかよ...

というわけで1つめにダミーのスイッチを設置してd-noneで非表示にして、2つめに本命のトグルスイッチを設置します。

<div class="d-none"><input id="dummy" type="checkbox" value=""></div>

<div class="toggle_switch">
  <input id="btn-mode" type="checkbox" value=""><label for="btn-mode"></label>
</div>

この方法でうまくいきました!

まとめ

まだ解決できていない問題があります。

・端末でダークモードに設定していると、ハンバーガーメニューが黒いままなので背景に溶け込んで見えない

・モードに関わらずスイッチは初期状態

なんでかなあ。今後の課題とします。

ブルーライトがカットされてる!
ダークモードで世界が変わる!

この記事を書いた人
みやの
Web・DTP担当

Contact Us

ご意見、ご相談、料金のお見積もりなど、お気軽にお問い合わせください。

お問い合わせはこちら

TOP