CSSのlight-dark()関数でライトモードとダークモードのスタイルを簡単に定義できて便利すぎる!
Post on:2023年10月31日
CSS Color Module Level 5に追加された新しい関数light-dark()
を使用すると、ライトモードとダークモードのスタイルを簡単に定義できるようになります。
下記のようにlight-dark(#333, #ccc)
と記述すると、テキストのカラーにライトモードでは#333
が、ダークモードでは#ccc
が適用されます。
Easy Light-Dark Mode Color Switching with light-dark()
by Bramus!
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
- はじめに
- ライトモードまたはダークモードへの対応
- light-dark()関数によるライトモードとダークモードの対応
- <color>値以外への対応は?
- light-dark()関数のブラウザサポート
- light-dark()関数の使い方
はじめに
ライトモードとダークモードのどちらが使用されているかで色を変更するには、通常prefers-color-scheme
メディアクエリを使用します。これを簡単にするために、CSSにはlight-dark()
というユーティリティ関数が用意されています。
light-dark()
関数は、2つの色の値を引数として受け取ります。ライトモードとダークモードのどちらを使用しているかに基づいて、1番目または2番目の引数をその要素に適用します。
1 |
light-dark(<color>, <color>); |
ライトモードまたはダークモードへの対応
まずは、通常している方法を見てましょう。
使用されているライトモードまたはダークモードに基づいて色(またはその値)を変更するには、prefers-color-scheme
メディアクエリを使用してカスタムプロパティ(CSS変数)の値を変更します。
1 2 3 4 5 6 7 8 9 |
:root { --text-color: #333; /* ライトモードの値 */ } @media (prefers-color-scheme: dark) { :root { --text-color: #ccc; /* ダークモードの値 */ } } |
ダークモードを実装すると、通常各要素の色を変更するための重複したカスタムプロパティが必要になります。
1 2 3 |
body { color: var(--text-color); } |
light-dark()関数によるライトモードとダークモードの対応
W3CのCSS Color Module Level 5に新しく追加されたのが、light-dark()
関数です。この関数は、2つの色の値を引数として受け取ります。ライトモードとダークモードのどちらを使用しているかに基づいて、1番目の引数または2番目の引数を出力します。
1 |
light-dark(<color>, <color>); |
light-dark()の仕様によると、
この関数は、使用されている配色がlight
か不明な場合は1番目の<color>
値を、使用されている配色がdark
の場合は2番目の<color>値を計算します。
使用されるカラースキームはユーザーのライト・ダークモード設定だけでなく、color-scheme
プロパティの値にも基づきます。これはシステムカラーの計算方法と似ています。
参考: CSS System Colors
color-scheme
プロパティは、要素がどのカラースキームでレンダリングされるように設計されているかを示すことができます。これらの値はユーザーの好みに応じてネゴシエートされ、結果として使用される配色が決まります。
つまり、light-dark()
が機能するためには、最初にcolor-scheme
宣言をしておきます。
1 2 3 4 5 6 7 |
:root { color-scheme: light dark; } :root { --text-color: light-dark(#333, #ccc); /* ライトモードでは1番目の値、 ダークモードでは2番目の値を返します。 */ } |
color-scheme
宣言は、特定のモードに強制することもできます。
1 2 3 |
.dark { color-scheme: dark; /* この要素と子に対して、常にdarkを返します。 */ } |
light-dark()
に見覚えがある人がいるかもしれません。Chromiumは以前に-internal-light-dark()
を内部的にサポートしていました。この機能に基づいてCSS Working Groupで同様の機能が提案され、その結果がこのlight-dark()
です。
ただし、任意のタイプの値を対象とする-internal-light-dark()
とは異なり、light-dark()
は色にのみ使用できます。
<color>値以外への対応は?
light-dark()
へのフィードバックでよくあるのは、できることがかなり限定されているということです。light-dark()
は<color>
値でのみ動作するため、それは正しいことでありますが、現在は最終的なソリューションに向けた中間的なステップであるため意図的なものでもあります。
CSS Working Group issueで提案されているように、最終的なゴールはschemed-value()
という関数を用意することです。その関数でできることは、
color-scheme
の任意の値に応答する。<color>
値以外を返す。
たとえば、下記のような感じです。
1 2 3 4 5 6 7 |
:root { color-scheme: dark light custom; } body { color: schemed-value(light hotpink, dark lime, custom rebeccapurple); } |
しかし、現時点ではlight-dark()
しかありあません。ブラウザでできることの現実と一致しているので、個人的にはこれでいいと思います。
- なぜなら、現在のブラウザは
color-scheme
の<custom-ident>
をサポートしていないため、light
かdark
のみをサポートしています。そのため、現時点では他の値をサポートしても意味がありません。 - また、
<color>
値しか扱えないのは、パーサーがパースする値の型を事前に知っておく必要があるからです。light-dark()
は<color>
であると明示的に定義されています。
非常に広範囲なschemed-value()
からスリム化されたlight-dark()
へと機能の範囲を絞り込むことで、関数を現状のまま定義できるようになりました。
また、light-dark()
という名前と構文は非常に覚えやすく、使いやすいと思います。そしてもっとも重要なことは今日デベロッパーが抱えている一般的なユースケースに対するソリューションを提供するということです。
schemed-value()
が使用できるようになると、light-dark()
はその構文の糖分になります。
1 |
light-dark(<color>, <color>); = schemed-value(light <color>, dark <color>); |
light-dark()関数のブラウザサポート
2023年10月現在、Firefox 120のみでサポートされています。
【訳者注】Chromeのデベロッパーに取りあげられたので、意外と早くサポートされるかもしれません。
下記のデモは、現在使用しているブラウザがCSSのlight-dark()
関数をサポートしているかどうかチェックできます。
See the Pen
CSS light-dark() Support test by coliss (@coliss)
on CodePen.
各ブラウザのサポートに関する最新情報を得るには、下記をチェックしてください。
- Chromium/Blink: Issue #1490618
- Firefox/Gecko: Issue #1856999
- Safari/WebKit: Issue #262914
light-dark()関数の使い方
下記のデモでは、light-dark()
関数をサポートしているブラウザで表示した場合、ライトモードとダークモードの切り替えに反応する.auto
とラベル付けされたいくつかのdiv
要素が表示されます。.light
あるいは.dark
のクラスを持つdiv
要素は強制的に適切なモードになります。
See the Pen
CSS light-dark() Demo by coliss (@coliss)
on CodePen.
CSSは、下記の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#demo { color-scheme: light dark; .dark { color-scheme: dark; } .light { color-scheme: light; } & div { background: light-dark(#d4d4d4, #000); color: light-dark(#333, #ccc); } } |
sponsors