CSS 相對顏色語法

根據其他顏色的管道和值建立新顏色。

Adam Argyle
Adam Argyle

Chrome 119 提供 CSS 色彩等級 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(從綠色 r g b / alpha) 語法的圖表,箭頭從綠色頂端離開,並弧形進入函式的 rgb 開頭,這個箭頭會分成 4 個箭頭,然後指向相關變數。4 個箭頭分別代表紅色、綠色、藍色和 alpha。紅色和藍色的值為 0,綠色為 128,alpha 為 100%。

上圖顯示原始顏色 green 會轉換為新顏色的色彩空間,並轉換為以 rgbalpha 變數表示的個別數字,然後直接用作新 rgb() 顏色的值。

雖然這張圖片顯示了細目、程序和變數,但它也不會變更顏色。變數會以未變更的形式放回顏色,因此仍會顯示綠色。

from 關鍵字

語法的第一部分是 from <color> 新增的部分,用於指定顏色。在您指定值之前,以下是程式碼範例,其中所有新增項目都是 from green,就在指定 rgb() 值之前。

.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%  */

現在是深藍色!色相加倍,將 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,然後透過增加 l (亮度) 通道 (將目前值乘以 1.25) 來淡化藍色。這會將藍色亮度推向白色 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,然後將 l (亮度) 通道減少 25%,並將值乘以 .75,藉此使藍色變暗。這會將藍色推向黑色 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,根據相對 50% 增加 orchid 的振動強度。

.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);
}

色彩增強功能

這項效果與飽和色相似,但在某些方面有所不同。首先,這是 chroma 變更,而非 saturation 變更,這是因為可提升至高動態範圍的色彩空間不會使用飽和度。採用 chroma 的色彩空間具有高動態範圍功能,可讓作者進一步提升色彩鮮豔度,甚至超越飽和度。

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

調整顏色不透明度

製作半透明顏色變化版本是設計系統中常見的顏色調整方式之一。如有遺漏,請參閱本文的引言中提供的範例,其中清楚說明瞭問題空間。

以特定值調整不透明度

.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%);
}

反轉顏色

色彩反轉是色彩資料庫中常見的色彩調整函式。達成這項目標的方法之一,是將顏色轉換為 RGB,然後將每個管道的值從 1 中減去。

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

互補色

如果您的目標不是反轉顏色,而是要補足顏色,那麼色調旋轉功能可能會是您想要的。請選取以角度提供色調的色彩空間,然後使用 calc() 旋轉色調至所需的角度。尋找顏色互補值的方法是旋轉半圈,在本例中,您可以將 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 類別會示範 L* 與 60 的差異。由於原始顏色是深色 (亮度值低),因此亮度管道會加上 60% (.6)。這項技巧可用於在淺色背景上找出對比度高、色調相同的深色文字顏色。

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

對比較淺的顏色

.well-contrasting-lighter-color 類別也展示了 L* 與 60% 的差異。由於原始顏色是淺色 (高值亮度),因此亮度管道會減去 .60。

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

調色盤

相對色彩語法非常適合用來建立調色盤。由於可用的色彩空間數量,因此特別實用且強大。以下範例都使用 OKLCH,因為亮度通道可靠,且色調通道可旋轉且不會產生副作用。最後一個範例會示範如何結合亮度和色相旋轉調整功能,獲得更有趣的結果!

請開啟這些範例的原始碼,然後嘗試變更 --base-color,看看這些色版的動態效果。很有趣!

如果你喜歡觀看影片,我會在 YouTube 上使用 OKLCH 在 CSS 中建立色版,提供深入資訊。

單色調色盤

如要建立單色調色盤,請使用相同色調建立調色盤,但亮度和暗度會有所不同。中間的顏色是調色盤的原始顏色,兩側各有兩個較淺和較深的變化版本。

: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 製作的調色盤

Open Props 是免費 CSS 變數的程式庫,提供採用此策略建構的色板,並可透過匯入輕鬆使用。這些調色盤都是以可自訂的顏色建立,只要指定顏色,系統就會吐出調色盤!

類似色調色盤

由於 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));
}

四元音色調

四元色調色盤是指在色輪上平均分割四種顏色,製作出沒有明顯主色調的調色盤。您也可以將其視為兩組互補色。只要妥善運用,就能發揮極大作用。

這是顏色理論的簡略說明,但如果您有興趣,這足以讓您開始使用更複雜的四元色調色盤。

: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% 或 5 度,比上述使用深粉紅的範例更為細微,因此您必須仔細觀察,才能發現這個排行榜為何能以任何色調呈現出如此優雅的效果。

請務必變更排行榜下方滑桿中的色調,並查看相對顏色語法如何創造美麗的色彩瞬間。

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))
  );
}