Back

CSSにおける相対カラー構文の解説

CSSにおける相対カラー構文の解説

ブランドカラーの半透明バージョンを作成するためだけに、十数個のカスタムプロパティを定義した経験があるなら、CSS相対カラー構文が解決する問題をすでに理解しているでしょう。この機能を使用すると、最新のCSSカラー関数内で既存の色から直接新しい色を派生させることができます。プリプロセッサも、JavaScriptも、追加の変数も必要ありません。

重要なポイント

  • CSS相対カラー構文は、fromキーワードを使用して既存の基準色から新しい色を派生させ、個々のチャンネルを変更可能な変数として公開します。
  • rgb()hsl()hwb()lab()lch()oklab()oklch()で動作します。
  • OKLCHは、明度チャンネルが知覚的に均一であるため、色操作に推奨される色空間であり、色相全体で視覚的に一貫した結果を生成します。
  • 相対カラーはトークンベースのデザインシステムに自然に統合され、1つの基本色を定義するだけで、プリプロセッサやビルドステップなしですべてのバリエーションを派生させることができます。

CSS相対カラー構文とは?

CSS Color Level 5仕様で定義されているCSS相対カラーは、既存の色(基準色と呼ばれる)を取得し、その個々のチャンネルを変数として使用して新しい色を構築できます。重要な追加要素はfromキーワードです。

基本構造は次のとおりです:

color-function(from <origin-color> channel1 channel2 channel3)

ブラウザがfromに遭遇すると、基準色をターゲット色空間に変換し、各チャンネルを名前付き変数として公開し、それらの変数を変更したまま、または変更せずに出力値として渡すことができます。

これは、rgb()hsl()hwb()lab()lch()oklab()oklch()などの最新のCSSカラー関数で機能します。

CSS from カラー構文の仕組み

次の簡単な例を見てみましょう:

/* 基準色: green */
/* 公開されるチャンネル: r=0, g=128, b=0 */
color: rgb(from green r g b); /* rgb(0 128 0)を出力 */

ここでは出力は入力と同じですが、真の力はcalc()を使用して個々のチャンネルを変更できることです:

/* 色相を180度回転させて補色を取得 */
background: hsl(from blue calc(h + 180) s l);

/* 明度チャンネルを乗算して明るくする */
background: oklch(from blue calc(l * 1.25) c h);

/* 別の変数なしで不透明度を下げる */
background: rgb(from lime r g b / 50%);

チャンネル値は関数内で純粋な数値に解決されるため、calc()による算術演算は単位の不一致なくスムーズに機能します。

OKLCH相対カラーを使用する価値

すべての色空間が操作に対して同等ではありません。HSLは馴染み深いですが、その明度チャンネルは知覚的に均一ではありません。lを同じ量だけ調整しても、異なる色相では視覚的に一貫性のない結果が生じます。

OKLCHはこれを解決します。その明度チャンネルは知覚的に均一であり、+0.1のシフトは色相に関係なく同じ視覚的ステップのように見えます。これにより、ティント、シェード、アクセシブルなコントラストペアを生成するための強力な選択肢となります。

知覚的色空間に馴染みがない場合は、Björn Ottossonによって導入されたOKLab/OKLCHカラーモデルがこれらの新しい色空間の背後にある理論を説明しています。

/* 25%暗くする */
background: oklch(from var(--color-primary) calc(l * 0.75) c h);

/* 高コントラストのテキストカラーを生成 */
color: oklch(from var(--color-primary) calc(l + 0.6) c h);

OKLCHの明度チャンネルは0から1の範囲であるため、calc(l + 0.6)のシフトはかなり大きいことに注意してください。有効範囲を超える値は、ブラウザによって自動的にクランプされます。

相対カラー vs. color-mix()

これら2つのCSSカラー機能は異なる目的を果たします。color-mix()は、指定された比率で2つの色をブレンドします。CSS相対カラーは、単一の基準色のチャンネルを直接操作します。ホバー状態、ミュートされたバリアント、または不透明度調整されたトークンが必要な場合は、相対構文が適切なツールです。2つの異なる色の間を補間する必要がある場合は、color-mix()を使用してください。

トークンベースのデザインシステムへの組み込み

これがCSS相対カラーが真に輝く場面です。1つの基本トークンを定義し、そこからすべてのバリエーションを派生させます:

:root {
  --color-primary: #3b82f6;

  --color-primary-hover:    oklch(from var(--color-primary) calc(l * 0.9) c h);
  --color-primary-active:   oklch(from var(--color-primary) calc(l * 0.8) c h);
  --color-primary-disabled: oklch(from var(--color-primary) l c h / 0.5);
  --color-on-primary:       oklch(from var(--color-primary) calc(l + 0.6) c h);
}

--color-primaryを変更すると、すべての派生トークンが自動的に更新されます。Sass関数もビルドステップも必要ありません。

ブラウザサポート

相対カラー構文は、Chromium、Firefox、Safariの最新バージョンでサポートされています。@supportsを使用して安全に制御できます:

@supports (color: rgb(from white r g b)) {
  /* 相対カラー構文が利用可能 */
}

サポートしていないブラウザの場合は、相対カラー宣言の前にフォールバックカラーを提供します。カスケードにより、古いブラウザは静的な値を使用し、最新のブラウザはそれを上書きします:

.button {
  background: #3b82f6;
  background: oklch(from var(--color-primary) calc(l * 0.9) c h);
}

まとめ

CSS相対カラー構文は、プリプロセッサロジックのカテゴリ全体を、単一の読みやすいパターンに置き換えます。知覚的に一貫した明度調整にはOKLCHを選択し、直接的な彩度制御が必要な場合はhsl()を使用し、すべてをカスタムプロパティに接続することで、1つのソーストークンからパレット全体を同期させることができます。

よくある質問

はい。var()を使用して任意のカスタムプロパティを基準色として渡すことができます。例えば、oklch(from var(--brand-color) calc(l * 0.8) c h)は期待通りに動作します。ブラウザは最初に変数を解決し、次に結果の色をターゲット色空間に変換してそのチャンネルを公開します。

ブラウザは範囲外の値を自動的にクランプします。例えば、calc()式がOKLCHの明度を1より上または0より下に押し上げた場合、ブラウザはそれを有効範囲にクリップします。つまり、ほとんどの場合、オーバーフローに対して手動で保護する必要はありません。

通常の使用では、パフォーマンスへの影響は無視できます。ブラウザは、他のプロパティでcalc()を解決するのと同様に、計算値時に相対カラーを解決します。単一ページに数千の相対カラー宣言がない限り、測定可能な差が現れることはありません。

1つの変換の結果が有効なカラー値に解決される場合、相対カラー関数を連鎖させることができます。実際には、開発者は相対カラー計算の結果をカスタムプロパティに割り当て、それを別の変換の基準色として使用することが多く、コードの可読性を保ちながら複数ステップのカラー操作を可能にします。

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay