根據其他顏色的管道和值建立新顏色。
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
關鍵字後方的顏色。瀏覽器會轉換並分解這個原始顏色,並提供這些部分做為變數,以便在新的顏色定義中使用。
上圖顯示原始顏色 green
會轉換為新顏色的色彩空間,並轉換為以 r
、g
、b
和 alpha
變數表示的個別數字,然後直接用作新 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
,完全改變顏色。這會沿著色盤旋轉色相,這是個簡單的訣竅,可透過 圓柱色彩空間 (例如 HSL、HWB、LCH 和 OKLCH) 輕鬆完成。
如要以視覺化方式查看管道的值,以便在不需要猜測或背誦規格時,也能正確計算,請試試這個相對顏色語法管道值工具。它會根據您指定的語法顯示每個管道的值,讓您確切瞭解可用的值。
檢查瀏覽器支援情形
@supports (color: rgb(from white r g b)) {
/* safe to use relative color syntax */
}
用途和示範
以下範例和用途有許多替代語法,可產生類似或相同的結果。變化來自色彩空間和提供的通道。
此外,許多範例會使用 by
和 to
的詞彙來顯示色彩調整。顏色變更 by
是相對顏色變更,也就是使用變數的值,並根據其目前的值進行調整。顏色變更 to
是絕對顏色變更,也就是不使用變數的值,而是指定全新的值。
您可以在這個 Codepen 集合中找到所有示範。
調亮顏色
在調整色彩亮度時,OKLCH、OKLAB、XYZ 或 sRGB 色域可提供最可預測的結果。
減淡效果
以下範例 .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))
);
}