Post on:2025年3月6日
sponsorsr
先週、CSSで関数を自分で定義できるカスタム関数が使えるようなる(紹介記事)ことをお伝えしましたが、続報として、なんとif()
関数も使えるようになるそうです。すでにChrome Canaryではif()
関数をCSSで使用できます。
CSSで使えるif()
関数は、if()
はもちろん、else
も使用でき、条件付きで値を選択できるようになります。
CSS @function + CSS if() = 🤯
by Bramus!
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
CSS Custom Functions are coming(翻訳記事)で紹介したように、CSSのカスタム関数(CSS@function
)のプロトタイプを初めて見ました。Chromeではさらにプロトタイプはネストされたコンテナクエリもサポートされ、CSSによるif()
も追加されました。
これは以前にも言いましたが、これまでのCSSを大きく変えるゲームチェンジャーです!
2025年3月現在、CSSのカスタム関数もif()
もブラウザに実装されていません。ただし、Chrome Canaryではプロトタイプ化されており、フラグを有効にすると、機能します。
まずは、CSS Custom Functions are coming(翻訳記事)で作成したカスタムの--light-dark()
関数をご覧ください。このカスタム関数はCSSのlight-dark
関数とは異なります。
1 2 3 4 5 6 7 | @function--light-dark(--light,--dark){ result:var(--light); @media(prefers-color-scheme:dark){ result:var(--dark); } } |
CSSのlight-dark
関数では<color>
値しか扱えませんが、カスタムの--light-dark()
関数は<color>
値に限定されず、あらゆる値で動作します。しかし、light-dark
関数とは異なるので、ローカルのカラースキーム値には応答できないため、@media
で判定する必要があります。
※デモはChrome Canaryでご覧ください。
See the Pen
Custom CSS Custom Functions: --light-dark() by coliss (@coliss)
onCodePen.
前回の記事の最後で示唆したように、ネストされたコンテナクエリやCSSでif()
がサポートされれば、この制限は取り除かれます、そしてその日が早くも来ました!
ここで紹介するコードではコンテナクエリが使用されるため、常にラッパー要素が必要です。if()
を使用する次のセクションでは、この追加のラッパー要素は必要ありません。
前回の記事以降、Chromeのプロトタイプはアップデートされ、カスタム関数内のネストされたコンテナクエリもサポートされるようになりました。これにより、次のように要素ごとにライト・ダークを設定できるようになります。
--scheme
というカスタムプロパティを使用して、要素に優先カラースキームを設定します。--scheme
の値に対応するスタイルクエリを使用して、--light-dark()
関数を修正します。--scheme
に設定できる値は、light
,dark
,system
の3つです。light
またはdark
が設定されると、カラースキームは強制的にその値になります。
関数は、下記のようになります。
1 2 3 4 5 6 7 8 9 | @function--light-dark(--light,--dark){ /* --light の値がデフォルト */ result:var(--light); /* コンテナにdarkが設定されている場合は、--dark値を使用 */ @containerstyle(--scheme:dark){ result:var(--dark); } } |
@funciton
内では--light
と--dark
の値が関数の引数として渡されます。ただし、--scheme
カスタムプロパティは関数が呼び出された要素から読み込まれます。
--scheme
に何らかの値があることを確認するために、prefers-color-scheme
の値に応じて:root
をそれを設定します。prefers-color-scheme
値はsystem
の--scheme
値のサポートを有効にするために--root-scheme
に複製されますが、これについては後述します。
1 2 3 4 5 6 7 8 9 | :root{ --root-scheme:light; --scheme:light; @media(prefers-color-scheme:dark){ --root-scheme:dark; --scheme:dark; } } |
要素ごとに優先カラースキームを設定できるようにするために、私はdate-scheme
HTML属性を使用することにしました。この属性はattr()
関数を使用してCSSで値にパースされます。値がlight
またはdark
の場合は、その値を直接使用します。値がsystem
の場合は、コードは--root-scheme
プロパティの値を使用します。ネストされたライト・ダークのコンテキストで適切に動作するように、コードは@scope
を使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* data-scheme属性から--schemeを上書きできるようにする */ @scope([data-scheme]){ /* 属性から値を取得する */ :scope{ --scheme:attr(data-schemetype(<custom-ident>)); } /* systemを設定すると、--root-scheme値が使用されます */ :scope[data-scheme="system"]{ --scheme:var(--root-scheme); } /* これにより、ネイティブのlight-dark()も機能するようになります */ :scope>*{ color-scheme:var(--scheme); } /* 属性を持つ要素は追加のラッパー要素なので、その内容を表示するだけでよいです */ display:contents; } |
attr()
関数の新機能については、CSS attr() gets an upgrade(翻訳記事)をご覧ください。
ここまでのCSSをまとめてみます。
まずは、CSS。
1 2 3 4 5 6 7 8 9 10 | [data-scheme]>*{ color:light-dark(#333, #e4e4e4); background-color:light-dark(aliceblue,#333); border:4px--light-dark(dashed,dotted)currentcolor; font-weight:--light-dark(500,300); font-size:--light-dark(16px,18px); transition:all0.25sease,border-style0.25sallow-discrete; } |
続いて、HTML。
1 2 3 4 5 | <divdata-scheme="light"> <divclass="stylable-thing"> … </div> </div> |
実際の動作は、デモページでご覧ください。
動作を確認するには、Chrome CanaryでExperimental Web Platform Featuresフラグを有効にします。
See the Pen
Custom CSS Custom Functions + Nested Style Queries (+ attr()): --light-dark() by coliss (@coliss)
onCodePen.
Chrome Canary 135.0.7022.0では、インラインのif()
関数を使用できます。この関数により、宣言内で条件付きで値を設定できるため、コンテナクエリのアプローチに必要な追加のコンテナ要素を省略できます。
CSSのif()
関数は条件としてスタイルクエリも受け入れるため、全体的なアプローチは同じです。しかし、結果として得られるコードははるかに短くなります。
1 2 3 4 5 6 | @function--light-dark(--light,--dark){ result:if( style(--scheme:dark):var(--dark); else:var(--light) ); } |
また、--scheme
をlight
またはdark
に設定するコードも短くなり、--root-scheme
値にフォールバックする方が簡単になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | :root{ --root-scheme:light; --scheme:light; @media(prefers-color-scheme:dark){ --root-scheme:dark; --scheme:dark; } } @scope([data-scheme]){ :scope{ --scheme-from-attr:attr(data-schemetype(<custom-ident>)); --scheme:if( style(--scheme-from-attr:system):var(--root-scheme); else:var(--scheme-from-attr) ); color-scheme:var(--scheme);/* ネイティブのlight-dark()を動作させる */ } } |
使用方法は前述と同じですが、[data-scheme]
要素でカラースキームに依存するスタイルを直接設定できるという違いがあります。
1 2 3 4 5 6 7 8 9 10 | [data-scheme]{ color:light-dark(#333, #e4e4e4); background-color:light-dark(aliceblue,#333); border:4px--light-dark(dashed,dotted)currentcolor; font-weight:--light-dark(500,300); font-size:--light-dark(16px,18px); transition:all0.25sease,border-style0.25sallow-discrete; } |
実際の動作は、デモページでご覧ください。
動作を確認するには、Chrome CanaryでExperimental Web Platform Featuresフラグを有効にします。
See the Pen
Custom CSS Custom Functions + Nested inline if() (+ attr()): --light-dark() by coliss (@coliss)
onCodePen.
私はCSSのカスタム関数だけでも非常に興奮しましたが、カスタム関数をif()
関数と組み合わせることでさらに高いレベルに引き上げることができます!
sponsors