CSS 相対色構文

別の色のチャネルと値に基づいて新しい色を作成します。

Adam Argyle
Adam Argyle

Chrome 119 では、CSS Color Level 5 の非常に強力なカラー機能があります。相対色の構文を使用すると、CSS 内で色をスムーズに操作でき、作成者やデザイナーは以下のことができるようになります。

相対カラー構文のは、色の不透明度を変更するには、色のチャネル(通常は HSL)のカスタム プロパティを作成し、最終的な色と最終的なバリアント カラーに組み立てる必要があります。これは、多数の色要素を管理することを意味し、すぐに煩雑になる可能性があります。

:root {
  --brand-hue: 300deg;
  --brand-saturation: 75%;
  --brand-lightness: 50%;

  --brand-hsl:
    var(--brand-hue)
    var(--brand-saturation)
    var(--brand-lightness);

  --brand-color: hsl(var(--brand-hsl));

  /* all this work just so I can set the opacity to 50% in a variant */
  --brand-color-variant: hsl(var(--brand-hsl) / 50%);
}

の相対色構文を使用すると、任意の色空間や構文でブランドカラーを作成し、はるかに少ないコードで半不透明度のバリアントを作成できます。また、スタイルとシステムの意図の読みやすさも大幅に向上します。

:root {
  --brand-color: hsl(300deg 75% 50%);
  --brand-color-variant: hsl(from var(--brand-color) h s l / 50%);
}

この投稿では、構文の学習一般的な色操作のデモを行います。

ビデオをお望みの場合、次の記事のほぼすべてがこの GUI チャレンジでカバーされています。

構文の概要

相対カラー構文の目的は、別の色から色を取得できるようにすることです。ベースカラーは元の色と呼ばれ、新しい from キーワードの後に続く色です。ブラウザは、この元の色を変換して分解し、新しい色定義で使用する変数として各部分を提供します。

構文 rgb(from green r g b / alpha)の図を示します。矢印は緑の上部から出て、RGB 関数の先頭に向かってアーチしています。この矢印は 4 つの矢印に分割され、関連する変数を指しています。4 つの矢印は、赤、緑、青、アルファです。赤と青の値は 0、緑は 128、アルファは 100% です。

上の図では、元の色の green が新しい色の色空間に変換され、rgbalpha 変数として表される個々の数値に変換され、新しい rgb() カラーの値として直接使用されます。

この画像は内訳、プロセス、変数を示していますが、色も変化していません。変数は変更されないまま色に戻されるため、緑色のままになります。

from キーワード

学習する構文の最初の部分は、色を指定する from <color> 部分です。これは、値を指定する直前になります。rgb() の値が指定されている直前に、from green だけが追加されています。

.syntax-introduction_same-colors {
  color: green;
  color: rgb(0 128 0);
  color: rgb(from green r g b);    /* result = rgb(0 128 0) */
}

この from キーワードは、関数表記の最初のパラメータとして、色の定義を相対色に変換します。from キーワードの後に、CSS は色(次の色を決める色)を想定します。

色変換

簡単に言うと、新しい色で使用するために緑色を r g および b チャンネルに変換します。

rgb(from green r g b)           /* r=0 g=128 b=0 */
rgb(from rgb(0 128 0) r g b);   /* r=0 g=128 b=0 */

カスタム プロパティの色

rgb from green の読み取りは非常に明確で、理解しやすいです。そのため、from の色に関する謎を取り除くことができるため、カスタム プロパティと相対色の構文は非常に一致しています。また、選択した形式で新しい色を作成する場合、通常はカスタム プロパティの色の形式について把握する必要はありません。

rgb(from rgb(255 105 180) r g b) /* ????? */
rgb(from var(--hotpink) r g b)   /* clear */

好みの色空間で作業する

色空間は、実用的な色表記を使って選択できます。

rgb(from hsl(120 100% 25%) r g b)     /*  r=0   g=128  b=0    */
hsl(from hsl(120 100% 25%) h s l)     /*  h=120 s=100% l=25%  */
hwb(from hsl(120 100% 25%) h w b)     /*  h=120 w=0%   b=50%  */
lch(from hsl(120 100% 25%) l c h)     /*  l=46  c=68   h=134  */

相対色の構文には、この変換ステップがあります。from の後の色は、相対色の先頭で指定された色空間に変換されます。入力と出力を一致させる必要はなく、非常に自由になります。

色空間を選択する能力は、好みよりも代替の種類に重点が置かれる傾向があるため、色空間を選択する能力も役に立ちます。この設定は、カラー形式やチャンネル タイプではなく、結果に含まれます。この点については、色空間がタスクごとに異なるため、ユースケースを説明するセクションで詳しく説明します。

変数を混在、照合、省略、繰り返す

この構文には奇妙ですが、興味深いことに、変数を順序どおりに並べる必要はなく、繰り返し可能です。

rgb(from green g g g)    /* rgb(128 128 128) */
rgb(from green b r g)    /* rgb(0 0 128) */
rgb(from green 0 0 g)    /* rgb(0 0 128) */

変数としての不透明度

この構文では、不透明度も alpha という名前の変数として指定されています。これは省略可能で、色分け機能を表す表記の / の後に配置されます。

rgb(from #00800080 r g b / alpha)             /* alpha=50% */
rgb(from rgba(0,128,0,.5) r g b / alpha)      /* alpha=50% */
rgb(from rgb(0 128 0 / 50%) r g b / alpha)    /* alpha=50% */

変数に対して calc() またはその他の CSS 関数を使用する

これまでは、緑色を何度も何度も作成してきました。構文、変換と分解のステップを学びます。次に、変数を変更し、入力と同じにならないように出力を変更します。

green                              /*  h=120 s=100% l=25%  */
hsl(from green calc(h * 2) s l)    /*  h=240 s=100% l=25%  */

今はネイビーだよ!色相を 2 倍にして、120 の色相を 240 に変換し、色を完全に変更しています。これにより、カラーホイールに沿って色相が回転します。これは、HSLHWBLCHOKLCH などの円柱の色空間を使用することで、非常にシンプルなトリックです。

チャネルの値を視覚的に確認して、仕様を推測したり、仕様を記憶したりせずに、計算を正しく行えるようにするには、こちらの相対色構文チャンネル値ツールをお試しください。指定した構文に基づいて各チャネルの値が表示されるため、どのような値を使用できるかを正確に把握できます。

ブラウザのサポートを確認する

@supports (color: rgb(from white r g b)) {
  /* safe to use relative color syntax */
}

ユースケースとデモ

以下の例とユースケースには、類似または同じ結果を得るための多くの代替構文があります。これらのバリエーションは、色空間とそれが提供するチャネルによって決まります。

また、多くの例では、byto の言い回しを使用して色の調整を示しています。色の変更 by は相対的な色の変更です。つまり、変数の値を使用して、現在の値に基づいて調整を行います。色の変更 to は絶対的な色の変更です。変数の値を使用せず、まったく新しい値を指定する変更です。

すべてのデモは、こちらの Codepen コレクションにあります。

色を明るくする

OKLCH、OKLABXYZsRGB の色空間で明るめの色を使用すると、最も予測しやすい結果が得られます。

少し明るくする

次の .lighten-by-25 の例では、色 blue を取得して OKLCH に変換し、現在の値に 1.25 を掛けて l(明度)チャネルを増やし、青色を明るくしています。これにより、青色の明度が 25% 白色に近づきます。

.lighten-by-25 {
  background: oklch(from blue calc(l * 1.25) c h);
}

特定の値に明るくする

次の .lighten-to-75 の例では、l チャネルを使用して blue を軽量化するのではなく、値を 75% に完全に置き換えています。

.lighten-to-75 {
  background: oklch(from blue 75% c h);
}

色を暗くする

色を明るくするのに効果的な色空間は、暗い色にも適しています。

一定量だけ暗くする

次の .darken-by-25 の例では、青色を取得して OKLCH に変換し、値に .75 を掛けて l(明度)チャネルを 25% 減らして青色を暗くしています。これにより、青色が黒色に 25% 押し上げられます。

.darken-by-25 {
  background: oklch(from blue calc(l * .75) c h);
}

指定した値まで暗くする

次の .darken-to-25 の例では、l チャネルを使用して blue を暗くするのではなく、値を 25% に完全に置き換えています。

.darken-to-25 {
  background: oklch(from blue 25% c h);
}

色の彩度を上げる

金額で彩度を上げる

次の .saturate-by-50 の例では、hsl()s を使用して、orchid のバイブレーションを相対 50% だけ増やしています。

.saturate-by-50 {
  background: hsl(from orchid h calc(s * 1.5) l);
}

特定の量まで飽和させる

次の .saturate-to-100 の例では、hsl()s チャネルを使用せず、目的の彩度値を指定しています。この例では、彩度が 100% に引き上げられます。

.saturate-to-100 {
  background: hsl(from orchid h 100% l);
}

色の彩度を下げる

一定量だけ彩度を下げる

次の .desaturate-by-half の例では、hsl()s を使用して、indigo の彩度を半分に下げています。

.desaturate-by-half {
  background: hsl(from indigo h calc(s / 2) l);
}

特定の値まで彩度を下げる

特定の量だけ彩度を下げるのではなく、目的の特定の値まで彩度を下げることができます。次の .desaturate-to-25 の例では、indigo に基づいて新しい色を作成していますが、彩度は 25% に設定されています。

.desaturate-to-25 {
  background: hsl(from indigo h 25% l);
}

色をブーストする

この効果は、色の彩度に似ていますが、異なる点がいくつかあります。まず、これは saturation ではなく chroma の変更です。これは、ハイ ダイナミック レンジにブーストできる色空間は彩度を使用しないためです。chroma を特徴とする色空間はハイ ダイナミック レンジに対応しており、彩度よりも色の鮮やかさを向上させることができます。

.increase-chroma {
  background: oklch(from orange l calc(c + .1) h);
}

色の不透明度を調整する

半透明な色のバリエーションの作成は、デザイン システムで最もよく行われる色調整の 1 つです。この記事の冒頭で紹介した例を見逃した場合は、問題領域の概要を示しています。

不透明度を一定量調整する

.decrease-opacity-by-25 {
  background: rgb(from lime r g b / calc(alpha / 2));
}
をご覧ください。

不透明度を特定の値に調整する

.decrease-opacity-to-25 {
  background: rgb(from lime r g b / 25%);
}

色を反転する

色反転は、カラー ライブラリにある一般的な色調整関数です。これを実現する 1 つの方法は、色を RGB に変換してから、各チャネルの値を 1 から減算することです。

.invert-each-rgb-channel {
  background: rgb(from yellow calc(255 - r) calc(255 - g) calc(255 - b));
}

色を引き立たせる

色を反転させることではなく、それを補完することが目的である場合は、色相回転が目的と考えられます。色相を角度として指定する色空間を選択し、calc() を使用して色相を必要な分だけ回転させます。色の補数を求めるには、0.5 回回転します。この場合、h チャネルに対して 180 の加算または減算を行うことで、その結果が得られます。

.complementary-color {
  background: hsl(from blue calc(h + 180) s l);
}

色のコントラストをつける

アクセス可能な色のコントラスト比を実現する方法として、L&midast;(Lstar)を検討してください。これは、calc() で LCH と OKLCH の(ほぼ)知覚的に均一な明度(L)チャネルを使用します。低コントラスト、中コントラスト、高コントラストのどちらをターゲットとするかによって、L&midast; のデルタは約 40、約 50、または約 60 です。

この手法は、LCH または OKLCH のどのような色相でもうまく機能します。

暗い色のコントラスト

.well-contrasting-darker-color クラスは、デルタ 60 の L* を示しています。元の色は暗い色(低い明度)であるため、明度チャネルに 60%(.6)が追加されます。この手法は、明るい背景でコントラストの効いた同じ色相で暗いテキスト色を見つけるために使用されます。

.well-contrasting-darker-color {
  background: darkred;
  color: oklch(from darkred calc(l + .60) c h);
}

明るめの色のコントラスト

.well-contrasting-lighter-color クラスも 60% のデルタで L* を示しています。元の色は明るい色(高い値の明度)であるため、明度チャンネルから 0.60 が差し引かれます。

.well-contrasting-lighter-color {
  background: lightpink;
  color: oklch(from lightpink calc(l - .60) c h);
}

カラー パレット

相対カラー構文は、カラーパレットの作成に非常に適しています。これは、利用可能な色空間の数が多いため、特に便利で効果的です。次の例では、明度チャネルの信頼性が高く、色相チャネルを副作用なしで回転できるため、OKLCH を使用しています。最後の例では、明度と色相の回転を調整してより興味深い結果を生成しています。

これらのサンプル ソースコードを開き、--base-color を変更して、パレットがいかに動的であるかを確認します。楽しい!

動画が気に入ったら、YouTube で OKLCH を使用して CSS でカラーパレットを作成する方法を詳しく説明します。

モノクロ パレット

モノクロのパレットを作成するには、同じ色相を使用し、明度と暗さにバリエーションがあるパレットを作成します。中央の色はパレットのソースカラーで、2 つの明るいバリアントと 2 つの暗いバリアントが左右どちらかに配置されます。

:root {
  --base-color: deeppink;

  --color-0: oklch(from var(--base-color) calc(l + .20) c h); /* lightest */
  --color-1: oklch(from var(--base-color) calc(l + .10) c h);
  --color-2: var(--base-color);
  --color-3: oklch(from var(--base-color) calc(l - .10) c h);
  --color-4: oklch(from var(--base-color) calc(l - .20) c h); /* darkest */
}
相対的な色構文と OKLCH で作成されたさまざまなパレットを試す

無料の CSS 変数のライブラリである Open Props には、この方法で作成されたカラーパレットが用意されており、インポートで簡単に使用できます。それらはすべてカスタマイズ可能な色で構築されており、色を指定するだけでパレットが見えます。

をご覧ください。

類似パレット

OKLCH と HSL では色相回転が非常に簡単であるため、類似のカラーパレットを作成するのは簡単です。好みの量で色相を回転させてベースカラーを変更すると、ブラウザで新しいパレットが作成されるのを確認できます。

:root {
  --base-color: blue;

  --primary:   var(--base-color);
  --secondary: oklch(from var(--base-color) l c calc(h - 45));
  --tertiary:  oklch(from var(--base-color) l c calc(h + 45));
}

トライアディック パレット

補色と同様に、トライアディック カラーパレットは、基本色を指定して、対立するが調和のとれた色相回転です。カラーホイールの中央を通る直線のように補色が反対側にある場合、トライアディック パレットは三角形の線のようなもので、基本色から均等に回転した 2 色を探します。これを行うには、色相を 120deg 回転させます。

これは色理論を若干単純化したものですが、興味があれば、より複雑なトライアディック パレットにすぐに着手できます。

:root {
  --base-color: yellow;
  --triad-1: oklch(from var(--base-color) l c calc(h - 120));
  --triad-2: oklch(from var(--base-color) l c calc(h + 120));
}

4 次元パレット

テトラディック パレットは、カラーホイールの周りを均等に分割された 4 色であり、明確な支配値のないパレットになります。2 つの補色のようなものと考えることもできます。適切に使用することで、非常に意味のある場合があります。

これは色理論をわずかに単純化したものですが、興味があれば、より複雑な四次元パレットにすぐに着手できます。

:root {
  --base-color: lime;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) l c calc(h + 90));
  --color-3: oklch(from var(--base-color) l c calc(h + 180));
  --color-4: oklch(from var(--base-color) l c calc(h + 270));
}

色相がわずかに回転したモノクロ

多くのカラー専門家が、この技を実践しています。問題は モノクロのカラースケールは かなり退屈なものだということですこの問題を解決するには、明度の変更に応じて、新しい色ごとにマイナーまたはメジャーな色相回転を追加します。

次の例では、見本ごとに明度を 10% 下げ、色相を 10 度回転させています。その結果、ホットピンクから藍色へのパレットが、グラデーションのようにシームレスに混ざり合っているように見えます。

:root {
  --base-color: deeppink;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) calc(l - .10) c calc(h - 10));
  --color-3: oklch(from var(--base-color) calc(l - .20) c calc(h - 20));
  --color-4: oklch(from var(--base-color) calc(l - .30) c calc(h - 30));
  --color-5: oklch(from var(--base-color) calc(l - .40) c calc(h - 40));
}
OKLCH と色相回転で構築されたこのリーダーボードをお試しください

次のリーダーボード インターフェースでは、この色相回転方法を使用しています。各リストアイテムは、ドキュメント内のインデックスを --i という変数として追跡します。このインデックスを使用して、彩度、明度、色相が調整されます。調整は 5% または 5deg のみとし、上の Deeppink の例よりもはるかに微妙です。そのため、このリーダーボードがこのような優雅な色相にできる理由に注意する必要があります。

リーダーボードの下にあるスライダーで色相を変更すると、相対的な色構文によって美しい色の瞬間が作成されるのを確認できます。

li {
  --_bg: oklch(
    /* decrease lightness as list grows */
    calc(75% - (var(--i) * 5%))

    /* decrease chroma as list grows */
    calc(.2 - (var(--i) * .01))

    /* lightly rotate the hue as the list grows */
    calc(var(--hue) - (var(--i) + 5))
  );
}