概要
- metaタグまたはスタイルシートで
color-scheme
を設定することで、ブラウザにカラーテーマを指定することができる。 - メディア特性の
prefers-color-scheme
を用いることで、ユーザがどのようなカラーテーマを要求しているかを取得できる。 - あまねけ!では
prefers-color-scheme
を用いてカラーテーマを自動で切り替え、従前より提供していた手動での切り替え機能も引き続き使用できるようにした。
color-theme
によるカラーテーマの指定
スタイルシートでの指定
CSSプロパティの color-scheme
を設定すると、ブラウザにカラーテーマを指定することができる。color-scheme
には以下の属性を設定できる。
normal
1light
dark
light
および dark
はスペース区切りで2つ以上並べることができ、この場合は先に指定したカラーテーマを推奨していることを示せる。
:root {
color-scheme: dark light;
}
カラーテーマを指定することで、自前でスタイルシートを用意することなくスクロールバーやフォーム要素を含むページの色合いを切り替えることができる。ただし、 color-scheme
はFirefox2およびInternet Explorerには対応していない。そのため、Firefoxが対応するまでは暗いカラーテーマのスタイルシートを用意しておく必要があるかもしれない。
color-scheme
は全ての要素に適用可能とされている。しかし、body要素以下に color-scheme: dark
を適用しつつ、ルート要素( :root
または html
)には color-scheme: dark
を指定しなかった場合は、文字色や背景色が変わらないなどの致命的な不具合がみられた3。
metaタグでの指定
color-scheme
はmetaタグでも設定でき、ルート要素に対して color-scheme
プロパティを設定するのと同じ効果を持つ。
<meta name="color-scheme" content="dark light">
prefers-color-scheme
による優先カラーテーマの取得
メディア特性の prefers-color-scheme
を用いることで、ユーザーがどのようなカラーテーマを優先的に要求しているかを取得できる。 prefers-color-scheme
は以下の値を持ちうる。
light
dark
prefers-color-scheme
をメディアクエリで用いることにより、ユーザの要求に合わせてスタイルを切り替えることができる。例えば、以下のようなスタイルシートはユーザの優先カラーテーマに合わせて背景色を切り替える。
/* 暗いカラーテーマ */
@media screen and (prefers-color-scheme: dark) {
body {
background-color: black;
}
}
/* 明るいカラーテーマ */
@media screen and (prefers-color-scheme: light) {
body {
background-color: white;
}
}
prefers-color-scheme
は多くのブラウザで対応しているものの、残念ながらInternet Explorerには対応していない4。上記のように全てのカラーテーマを prefers-color-scheme
メディアクエリに閉じ込めてしまうと、未対応のブラウザではいずれのスタイルも適用できないため、必要に応じてどちらかのテーマにフォールバックさせてもよいかもしれない。
/* 明るいカラーテーマ(またはデフォルト) */
@media screen {
body {
background-color: white;
}
}
/* 暗いカラーテーマ */
@media screen and (prefers-color-scheme: dark) {
body {
background-color: black;
}
}
あまねけ!での対応
あまねけ!では、これまでページ上部に toggle color scheme ボタン(切り替えボタン)を設置して、ブラウザのデフォルトカラーテーマ1とオリジナルの暗いカラーテーマを切り替えられるようにしていた。
color-scheme
の採用
まず、オリジナルの暗いカラーテーマを廃止し、 color-scheme
を用いてカラーテーマを切り替えることを検討したが、以下の理由で不採用とした。そのため、スクロールバーの色は従来通り明るいままとなっている5。
- metaタグでの
color-scheme
の指定は、読み込み後に手動で切り替えることができない。 - CSSプロパティでの
color-scheme
の指定は、疑似クラス:has()
がなければ手動で切り替えることができない。 - 一部のブラウザでは
color-scheme
でのカラーテーマの切り替えに対応していない。
ただし、ここでいう「手動で切り替える」とはスタイルシートのみを用いて切り替えることを指しており、JavaScriptでのプロパティの書き換えなどは含まない。
prefers-color-scheme
の採用
次に、 prefers-color-scheme
を用いて初期表示時のカラーテーマを自動で切り替えることを検討した。
prefers-color-scheme
に合わせて初期表示時のカラーテーマを設定した場合、切り替えボタンを用いた以下のような切り替えパターンが考えられる。
- 明るいカラーテーマで表示する場合
- (A)
prefers-color-scheme
に未対応で切り替えボタンを偶数回クリックした - (B)
prefers-color-scheme: light
で切り替えボタンを偶数回クリックした - (C)
prefers-color-scheme: dark
で切り替えボタンを奇数回クリックした
- (A)
- 暗いカラーテーマで表示する場合
- (D)
prefers-color-scheme
に未対応で切り替えボタンを奇数回クリックした - (E)
prefers-color-scheme: light
で切り替えボタンを奇数回クリックした - (F)
prefers-color-scheme: dark
で切り替えボタンを偶数回クリックした
- (D)
これまでの実装と影響範囲を考慮し、最終的には以下のような実装を行った。
@media screen and (prefers-color-scheme: light) {
/* (E) 奇数回クリックした際の挙動(暗いカラーテーマ) */
}
@media screen and (prefers-color-scheme: dark) {
/* (F) 偶数回クリックした際の挙動(暗いカラーテーマ) */
}
prefers-color-scheme
に未対応のブラウザへの対処
切り替えのロジック上、全てのパターンを網羅するには prefers-color-scheme
に未対応のブラウザと prefers-color-scheme: dark
であるブラウザを区別する必要がある。しかし、 prefers-color-scheme
に未対応のブラウザでは prefers-color-scheme
を含むメディアクエリを一切使用できず、 prefers-color-scheme
に未対応かどうかを明示的には検出できない。
この問題は、明るいカラーテーマをブラウザに頼らず明示的に設定することで解決できる。具体的には、フォールバックのスタイルには偶数回で明るく、奇数回で暗く切り替えるように設定し、 prefers-color-scheme: dark
のスタイルでそれらを逆に上書きすればよい。
@media screen {
/* (A,B) 偶数回クリックした際の挙動(明るいカラーテーマ) */
/* (D,E) 奇数回クリックした際の挙動(暗いカラーテーマ) */
}
@media screen and (prefers-color-scheme: dark) {
/* (C) 奇数回クリックした際の挙動(明るいカラーテーマ) */
/* (F) 偶数回クリックした際の挙動(暗いカラーテーマ) */
}
しかし、明るいカラーテーマを指定する手間と古いブラウザに対応するメリットを比較して、今回は prefers-color-scheme
に未対応のブラウザには対処しないことにした。今後、これらの環境では切り替えボタン自体が表示されない。もし切り替えボタンが使えなくなって困っていたら、すぐに対処するのでコメントなどで知らせてほしい。
強制ダークモードへの対処
また、サイトの color-scheme
指定にかかわらずブラウザのデフォルトカラーテーマを暗いものに切り替える機能、いわゆる強制ダークモードを適用している場合は、切り替えボタンをクリックしても2つの暗いカラーテーマ(ブラウザのデフォルトとサイトのオリジナル)しか使用できない。これについても、オリジナルの明るいカラーテーマを指定すれば解決できる。とはいえ、強制ダークモードを適用したいユーザが明るいカラーテーマを希望することは少ないと考えられるため、こちらも特に対処しない。
おまけ: チェックボックスでスタイルを切り替える
チェックボックスの状態を区別する :checked 擬似クラスセレクタ
と一般兄弟結合子 ~
を用いることで、CSSの機能だけでチェックボックスの状態に応じてスタイルを切り替えられる。現在、あまねけ!ではこの手法でカラーテーマを切り替えている。
この手法の欠点は、チェックボックスより階層が上の要素にはスタイルを当てられないということである。現状主要なブラウザで使用できる範囲では、JavaScriptを用いて親を辿らなければならない。「ある状態のチェックボックスを子に持つようなbody要素」のようなセレクタには、疑似クラス :has()
の実装が必要である。
<html>
<head>
<title>チェックボックスでスタイルを切り替える</title>
<style>
#main {
background-color: red;
}
input[type="checkbox"]#toggle:checked ~ #main {
color: #eee;
background-color: blue;
}
</style>
</head>
<body>
<input id="toggle" type="checkbox">
<section id="main">
<div>チェックボックスでスタイルを切り替える</div>
</section>
</body>
</html>