ダークモードの実装

CSS, JavaScript

ダークモード

Mac OS の Mojave(10.14 以降)には、ダークモード(Dark Mode)が搭載されている。
配色を暗めにして、ユーザーの目の負担を抑えたりする機能のこと。
従来の画面は、ライトモード(Light Mode)として区別される。

多くのネイティブアプリで対応が進んでいて、現在では一部の Web ページも対応している。
メディアクエリの 1 つで、ユーザーの操作などに応じて、CSS のスタイルを切り替えるもの。

ボタンでの実装

一部のページでは、トグル式、またはラジオボタンを用意して手動で切り替える。
また、localstorage に状態を保存するページもある。

How I added Dark Mode to my website

上記ページでは、.dark クラスの付け外しで対応している。

prefers-color-schemeでの実装

prefers-color-schemeは、Media Queries Level 5 のメディアクエリ。
ユーザーがライトモード、ダークモードどちらの配色を指定しているのかを判定する。
モダンブラウザで使用できる。

値は、no-preference(設定なし) | light | dark の 3 種類から指定できる。
CSS Variables と併せて、すでに一部のサイトに取り入れられている。

CSS

// ライトモードの時
@media (prefers-color-scheme: light) {
  :root {
    --main-bg-color: #fff;
    --main-text-color: #000;
  }
}

// ダークモードの時
@media (prefers-color-scheme: dark) {
  :root {
    --main-bg-color: #1e1e1e;
    --main-text-color: #fff;
  }
}

body {
  background-color: var(--main-bg-color);
  color: var(--main-text-color);
}

草案
"Can I use..." より対応バージョン
近づくダークモード対応の足音 | フロントエンド Blog | ミツエーリンクス
prefers-color-scheme を用いた Dark Mode 対応と User Preference Media Features | blog.jxck.io

matchmediaで分岐させる

prefers-color-scheme はメディアクエリなので、matchMedia を用いた対応が可能。
返ってきた MediaQueryList オブジェクトから matches で判定する。

JavaScript

const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;

また、Listener を設定できる。

JavaScript

window
  .matchMedia('(prefers-color-scheme: dark)')
    .addListener(({ matches }) => {
      if (matches) {
        // ダークモードの時の処理
      }
    });

ライトモードとダークモードでコンテンツを出し分ける、というのをやった。
あくまでユーザー支援の位置付けなので、演出として用いるのは問題だけど…。
(雲のイラストはこちらからお借りした: https://codepen.io/Mark_Bowley/pen/xEbuI)

prefers-color-schemeを用いて昼と夜を切り替えるアニメーション

対策

単に配色を置き換えるだけでなく、何箇所か対応が必要。

ダークモードの背景色には、#282c2f#1e1e1e などの黒に近いグレーが搭載されることが多い。
#000と文字 #fff の組み合わせはコントラストが高く、あまり採用されない。
テキストサイトェ…。

文字や背景にピュアブラックを使ってはいけない理由 | UX MILK
(元記事: Why You Should Never Use Pure Black for Text or Backgrounds)

文字

背景色が変わると、文字の印象も異なる。
下記リンク先の Stuff & Nonsense は、配色を変えるだけでなく、文章の line-heightword-spacing も調整している。

Redesigning your product and website for dark mode — Stuff & Nonsense

画像

その実態は CSS いじりということで、画像へのフォローも必要になる。
特に白地の背景だと辛くなってしまうので、透過 png や、SVG を検討した方が良いかもしれない。
一応、picture 要素のメディアクエリで画像を出し分けることは可能。

HTML

<picture>
  <source srcset="dark.jpg" media="(prefers-color-scheme: dark)">
  <img src="light.jpg">
</picture>

box-shadow

CSS

@media (prefers-color-scheme: dark) {
  * {
    box-shadow: none !important;
  }
}

あとは、SNS サイトなどのシェアアイコンで色を変えるのは、ライセンス違反の恐れがあるので確認が必須。

その他

WebKit の Inspector がダークモードに対応した時の記事