投稿日
テーマ切替の実装について考えてみる
テーマ切り替えの実装について考えてみます。カスタムプロパティのフォールバックトリックを使った、テーマ切替時に役に立つかもしれないTIPSもご紹介します。
ちょっと長い前置き
TIPSのご紹介に入る前に、ちょっと長い前置きとして、テーマ切り替えの実装について触れていきます。 問題点やモダンな方法をご紹介します。
テーマ切替の実装方法
以下の2通りが考えられます。
ボタンなどのクリックでの動的な切替の場合は、
:root
のstyle属性に、--theme: dark;
の様なカスタムプロパティを渡すことで実装します。
動的な切替方法は、ユーザー環境を強制的に切替えるとも捉えられるので、 賛否両論がある実装方法とも言えると思います。
:root[style*='--theme: light;'] { --font-color: black;}
:root[style*='--theme: dark;'] { --font-color: white;}
body { color: var(--font-color);}
システム設定に従う場合は、@media
でテーマの実装をします。
こちらはユーザー環境を優先した指定です。
:root { color-scheme: light dark;
@media (prefers-color-scheme: light) { --font-color: black; }
@media (prefers-color-scheme: dark) { --font-color: white; }}
body { color: var(--font-color);}
問題点
いづれの方法にせよ、重複したカスタムプロパティが存在するため、メンテナブルとは言いづらい状況です。 ウェブサイトやアプリケーションの成長に伴って、重複箇所も増えていくので辛くなっていきます。
救世主の登場
CSS Color Module Level 5
で定義されている、light-dark()
の登場により風向きが変わってきました。
MDN: light-dark()を見ると、 Baseline のNEWLY AVAILABLEになっていますので、 モダンブラウザでは利用可能な機能になっています。
以下のように書き換えることができます。
重複したカスタムプロパティがなくなりスッキリしました。
また、light-dark
という分かりやすい命名なので、コードの意図が明確になりました。
導入にあたっては、color-scheme: light dark;
の指定は必須になります。
:root { --font-color: light-dark(black, white);
color-scheme: light dark;}
body { color: var(--font-color);}
デザイントークンとして色を管理するかと思いますので、 ハードコーディングするよりも、カスタムプロパティとして管理するほうが好ましいです。
カスタムプロパティをテーマごとに管理するコストは発生しますが、 断然、こちらのほうが良いコードになると思います。
:root { --light-font-color: black; --dark-font-color: white; --font-color: light-dark(var(--light-font-color), var(--dark-font-color));
color-scheme: light dark;}
body { color: var(--font-color);}
動的に切替える場合は、color-scheme
の値をdark
かlight
に指定し直します。
ざっくりした例ではありますが、以下のようなコードで実装できるかと思います。
const root = document.documentElement
root.style.setProperty('color-scheme', 'dark') // or 'light'
light-darkでは出来ないこと
light-dark()
は、CSSで<color>
として定義されているものしか指定できません。
テーマ毎にアイコンを切替えたいなどといったことはできません。
構文は以下のとおりです。
light-dark() = light-dark(<color>, <color>)
CSSで<color>
として定義されているものの代表例です。
- キーワード
- 16進数のカラーコード
rgb()
,hsl()
,hwb()
,lab()
,oklab()
,lch()
,oklch()
- 相対カラー構文
TIPSのご紹介
テーマ切り替えにおいての、カスタムプロパティのフォールバックトリックの使い所をご紹介していきます。
前提条件
light-dark()
では、色以外を指定することができないため、
カスタムプロパティを使ったベーシックなロジックで実装します。
ただ、策定が進んでいるCSS Functions and Mixins Module
が勧告されることがあれば、この問題も解決できそうです。
(色以外も指定することが可能な、light-dark()
を定義可能になるため)
実装例
このようにフォールバックトリックを利用すると、テーマ毎にアイコンを切り替えるなどといった実装が可能になります。
light-dark()
を補助するような使い方として便利かもしれません。
動的な切替は、--theme
の値を切り替えることで実装します。
ユーザー環境ファーストな切替は、@media
でシステム設定に従って実装します。
/* 動的切替えな実装 */:root[style*='--theme: light;'] { --is-light: initial; --is-dark: ;}
:root[style*='--theme: dark;'] { --is-light: ; --is-dark: initial;}
/* ユーザー環境ファーストな実装 */:root { color-scheme: light dark;
@media (prefers-color-scheme: light) { --is-light: initial; --is-dark: ; }
@media (prefers-color-scheme: dark) { --is-light: ; --is-dark: initial; }}
/* 共通 */.example-icon { inline-size: 24px; aspect-ratio: 1; background-repeat: no-repeat; background-image: var(--is-light, url('...')) var(--is-dark, url('...'));}
デモ
動的に切り替えるパターンのデモを作ってみました。
フォールバックトリックでアイコン切り替え
See the Pen Untitled by Katuhisa Namizaki (@73log) on CodePen.
おわりに
テーマ切り替えの実装についてや、フォールバックトリックを使ったTIPSをご紹介しました。
テーマ切り替えについては、各社のUXに対する考えが現れる部分ではないでしょうか? ユーザーファーストな実装か、オプショナルな実装かは、テーマ切り替えに限らず言えることですので、 配慮した実装を心がけていきたいものです。
以上になります。