かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

CSS 今更のダークモード入門

ダークモード…やってこなかったので今更の入門したのでメモ。

prefers-color-scheme を使う

prefers-color-scheme をメディアクエリの中で使用することでデバイスのダークモード/ライトモードの設定を識別できます。

  • light ... ユーザーがシステムに、明色のテーマを持つインターフェイスにしたいと通知したか、アクティブな設定を示さなかったことを示します。
  • dark ... ユーザーがシステムに、暗色のテーマを持つインターフェイスにしたいと通知したことを示します。

cf. prefers-color-scheme - CSS: カスケーディングスタイルシート | MDN

例: CSS のカスタムプロパティ(変数) で指定しておくと楽

メディアクエリで指定できるので色以外もモードによってスタイルを変更することが可能

// デフォルトのカラー設定
:root {
  --text-color: #2e2827;
  --background-color: #fff;
}

@media (prefers-color-scheme: light) {
  // :root で指定してある場合は明示的に指定しなくても問題なさそう
  :root {
    --text-color: #2e2827;
    --background-color: #fff;    
  }
  // ダークモードの時だけ表示するユーティリティクラス
  .d-mode--dark {
    display: none !important;
  }
  // ライトモードの時だけ表示するユーティリティクラス
  .d-mode--light {
    display: initial !important;
  }
}

// ダークモード用の設定
@media (prefers-color-scheme: dark) {
  :root {
    --text-color: #f0f4f7;
    --background-color: #2e2827;    
  }

  .d-mode--dark {
    display: initial !important;
  }
  .d-mode--light {
    display: none !important;
  }
}

body {
  // 値を変数で指定しておくとモードによって自動的に使われる変数が変わる
  color: var(--text-color);
  background-color: var(--background-color);
}

カスタム属性を利用して切り替える

Chakra UI の様にカラーモードを指定できるボタンでテーマを切り替える場合はカスタム属性を利用すると便利。
ボタンで明示的にテーマを切り替えられるので、カラーモードをデバイスの設定よりアプリでのユーザー設定を優先することが可能になる。

作成方法は単純にカスタム属性で適応されるスタイルを用意して JavaScript で属性を変更するように切り替えれば良い。
カスタム属性で作成されたスタイルはメディアクエリより詳細度が高くなるので自動的に デバイスの設定 < アプリでのユーザー設定 となる

// デフォルトのカラー設定
:root {
  --text-color: #2e2827;
  --background-color: #fff;
}

// デバイスのモードに合わせた設定
@media (prefers-color-scheme: light) {
  :root {
    --text-color: #2e2827;
    --background-color: #fff;    
  }
}
@media (prefers-color-scheme: dark) {
  :root {
    --text-color: #f0f4f7;
    --background-color: #2e2827;    
  }
}

// カスタム属性でテーマを指定した場合の設定
// メディアクエリよりCSSの詳細度が高いのでこちらの指定が優先される
:root [data-theme=light] {
  --text-color: #2e2827;
  --background-color: #fff;
}
:root [data-theme=dark] {
  --text-color: #f0f4f7;
  --background-color: #2e2827;    
}

body {
  color: var(--text-color);
  background-color: var(--background-color);
}
<body data-theme="light"></body>

JavaScript を用いて body タグの data-themelight 又は dark に切り替えればテーマカラー変更できるようになる。
明示的にダークモードを指定しない場合はデバイスのモードを優先させたいなら :root [data-theme=light] の指定を削除すればOK。

Sample

  1. バイスがダークモードだと全体がダークモードになる
  2. トグルボタンのあるエリアは、トグルの状態でモードが変更になる (デバイスのダークモード指定より優先される)

See the Pen Dark mode Sample by KIKIKI (@kikiki_kiki) on CodePen.


[参考]

DARKER THAN BLACK 懐かしくなった