现在越来越多的浏览器开始支持 CSS Colors Module Level 4[1] 规范中定义的功能,其中包括在 CSS 中操作和显示颜色的多种方式。本文就来看看什么是颜色空间、如何在CSS中定义颜色,CSS Colors Module Level 4 中的新内容,以及如何在项目中使用颜色函数和特性。
CSS Colors Module Level 4:旨在扩展 CSS 中颜色相关的特性和功能。它提供了一些新的颜色表示方式、自定义调色板、透明度的控制等功能,并且对 CSS 中现有的颜色模块作出了一些修改和增强。CSS Colors Module Level 4 目前还处于候选推荐阶段,尚未正式发布为 W3C 推荐标准。
颜色空间是基于定义的颜色模型对颜色进行分组的系统。颜色空间提供了一种清晰和一致的方式来描述颜色,并且可以在保持外观不变的情况下将颜色转换到不同的颜色空间中。
在 CSS Colors Module Level 4 之前,CSS 中的颜色是在 RGB(红、绿、蓝)颜色空间和色域(颜色总范围)中定义的。
通过 CSS 对 HSL(色调、颜色和亮度)的支持,我们可以使用相同的 RGB 模型来定义颜色。
要在 RGB 颜色空间中生成颜色,可以以不同方式混合原色红色、绿色和蓝色以获得所需的结果。 可以把它想象成立方体中一个点的坐标,其中每个轴代表一种原色。
.red {
color: rgb(255 0 0);
}
.green {
color: rgb(0 255 0);
}
.blue {
color: rgb(0 0 255);
}
/* 黄色是红色和绿色的混合 */
.yellow {
color: rgb(255 255 0);
}
/* 青色是绿色和蓝色的混合 */
.cyan {
color: rgb(0 255 255);
}
要想在 CSS 中定义 RGB 颜色,可以选择使用颜色关键字(如 red 或 blue)、十六进制值 (#ff0000
) 或 rgb()
函数来定义红色、绿色和蓝色值,如上所示。
从 CSS Colors Module Level 4 开始,我们不再需要使用 rgba()
来定义具有 alpha 通道的 RGB 颜色,因为 rgb()
支持由斜线 (/) 分隔的 alpha 值,如下所示。
.named-color {
color: red;
}
.hex-color {
color: #ff0000;
}
.rgb-color {
color: rgb(255 0 0);
}
/* makes the color 50% transparent */
.rgba-semi-transparent {
color: rgb(255 0 0 / 0.5);
}
这里说明了如何使用关键字、十六进制值和 rgb()
函数定义相同的颜色,包括定义不透明。
CSS 颜色(第 3 级)中的 HSL 受到许多开发人员的欢迎,因为根据色轮选择色调会更加直观。我们可以使用 conic-gradient()
函数和 hsl()
函数制作色轮。
#color-wheel {
border-radius: 50%;
background: conic-gradient(
in hsl longer hue,
hsl(0deg 100% 50%),
hsl(360deg 100% 50%)
);
}
/* 对于不支持 conic-gradient 方法的浏览器 */
@supports not (background: conic-gradient(in hsl longer hue)) {
#color-wheel {
background: conic-gradient(red, yellow, green, cyan, blue, magenta, red);
}
}
结合这两个片段就可以制作一个色轮,循环显示 RGB 颜色空间中所有可用的色调:
hsl()
函数的工作方式与 rgb()
函数类似,但接受色相作为色轮上的角度,接受饱和度和亮度作为值。 与 rgb()
一样,可以向 hsl()
添加透明度(或不透明度)的 alpha 通道,这使得 hsla()
与 rgba()
一起成为遗留函数:
.red-hsl {
color: hsl(0 100% 50%);
}
.green-hsl {
color: hsl(120 100% 50%);
}
/* 使颜色 50% 不透明 */
.green-hsl {
color: hsl(120 100% 50% / 0.5);
}
HSL 函数还可以通过更改饱和度和亮度来改变颜色。 例如,如果为网站主题选择了特定颜色,可以修改颜色的饱和度和亮度以创建仍然适合主题的辅助颜色。 如下图所示:
.button {
color: hsl(200 100% 70%);
}
/* 按钮颜色的深色版本 */
.button--secondary {
color: hsl(200 100% 50%);
}
/* 较低的饱和度使按钮不那么生动 */
.button--inactive {
color: hsl(200 50% 70%);
}
此规范版本添加了许多使用不同方式表示颜色的新颜色函数,它们允许使用色调、亮度和饱和度等属性指定颜色。新的颜色函数使我们能够使用 RGB 色域之外的更鲜艳的颜色,因此在受支持的显示器上可以使用更大范围的颜色。
通过对额外空间和色域的支持,不再局限于在 RGB 颜色空间中描述颜色; 现在可以使用 Display P3、CIELAB、Oklab 色彩空间。
Display P3 使用 P3 色域并代表比 sRGB(标准 RGB)更宽的颜色范围。它对于现代显示器中使用的更鲜艳的颜色很有用。但是,需要为使用不支持它的设备的用户提供回退。
CIELAB 是一种统一色彩空间 (UCS),它根据人眼感知颜色的方式来定义颜色。该模型的主要目的是让颜色空间中两点之间相同的颜色距离对于观察者来说应该呈现出相同的差异。
Oklab 是一个较新的颜色空间,它使用与 CIELAB 相同的模型结构,但通过“视觉上相似颜色的数据集的数值优化”制成,因此值旨在比 CIELAB 更准确。
CIELAB 和 Oklab 颜色空间可以表示为三维空间,如下所示
新的颜色函数有助于描述上面提到的颜色空间中的值。
lab()
函数使用颜色空间中沿“a”和“b”轴的亮度、红色/绿色和黄色/蓝色来描述 CIELAB 颜色。
.lab-red {
color: lab(87.6 125 104);
}
.lab-green {
color: lab(87.8 -79 81);
}
lch()
函数符号使用亮度、色度和色调描述 CIELAB 颜色。色调是色轮上代表颜色的角度。
.lch-red {
color: lch(54.3 107 40.9deg);
}
.lch-green {
color: lch(87.8 113 134deg);
}
oklab()
函数使用 Oklab 颜色空间中沿“a”和“b”轴的亮度、红色/绿色和黄色/蓝色来描述 Oklab 颜色。
.oklab-red {
color: oklab(0.63 0.22 0.13);
}
.oklab-green {
color: oklab(0.87 -0.2 0.18);
}
除了新的颜色空间外,HWB 颜色还有一个 hwb()
函数,使用色调、白度和黑度定义。 HWB 使用 RGB 颜色空间,与 HSL 类似,但考虑的是白度和黑度,而不是饱和度和亮度:
.hwb-red {
color: hwb(0deg 0% 0%);
}
.hwb-light-red {
color: hwb(0deg 30% 0%);
}
.hwb-dark-red {
color: hwb(0deg 0% 30%);
}
/* 循环色轮 */
.hwb-green {
color: hwb(120deg 0% 0%);
}
.hwb-blue {
color: hwb(240deg 0% 0%);
}
color()
函数可以在预定义的颜色空间中指定颜色:
.green-display-p3 {
color: color(display-p3 0 1 0);
}
.blue-rec2020 {
color: color(rec2020 0 0 1);
}
.blue-srgb {
color: color(srgb 0 0 1);
}
还可以将 color()
函数与媒体查询结合起来以指定后备颜色空间:
.green-display-p3 {
color: color(display-p3 0 1 0);
}
@media (color-gamut: srgb) {
.green-display-p3 {
color: color(srgb 0 1 0);
}
}
rgb()
和 hsl()
函数的语法已更改,目的是使它们更易于使用。 不再需要分隔值的逗号,以使用斜杠指定颜色的 alpha 值:
/* 旧语法 */
rgb(255, 0, 0);
hsl(0, 100%, 50%);
/* 新语法 */
rgb(255 0 0);
hsl(0 100% 50%);
/* 带有 alpha 通道的新语法 */
rgb(255 0 0 / 0.5);
hsl(0 100% 50% / 0.5);
所有新函数都使用上述类型的语法,在值之间没有分隔逗号,并使用斜杠将 alpha 通道与颜色值分隔开。
插值是当计算两个已知值之间的一个或多个值时,因此如果有从红色到蓝色的渐变,插值就是计算哪些颜色在红色和蓝色之间的范围内的方式。 创建 linear-gradient()
或类似的 CSS 渐变时,可以使用 in
(用于插值)后跟渐变的颜色空间:
.hsl {
background: linear-gradient(in hsl, blue, red);
}
可以通过一个例子来比较不同颜色空间中的渐变,在标准 RGB 颜色空间中有一个从蓝色到红色的渐变,然后在不同的颜色空间中有相同的渐变:
.rgb {
background: linear-gradient(to right, blue, red);
}
.hsl {
background: linear-gradient(in hsl to right, blue, red);
}
.lch {
background: linear-gradient(in lch to right, blue, red);
}
.lab {
background: linear-gradient(in lab to right, blue, red);
}
.oklch {
background: linear-gradient(in oklch to right, blue, red);
}
.oklab {
background: linear-gradient(in oklab to right, blue, red);
}
有一些插值模式控制色轮周围的方向,色调应该在具有色调角度的颜色空间中插值:
HSL
HSL named
HSL (longer)
HSL named (longer)
Standard fallback
/* 从 39度到 60 度,绕色轮取最短路径 */
.hsl {
background: linear-gradient(
to right in hsl,
hsl(39deg 100% 50%),
hsl(60deg 100% 50%)
);
}
/* 也可以使用命名颜色 */
.hsl-named {
background: linear-gradient(to right in hsl, orange, yellow);
}
/* 这个渐变在色轮周围通过 0 循环回来 */
.hsl-longer {
background: linear-gradient(
to right in hsl longer hue,
hsl(39deg 100% 50%),
hsl(60deg 100% 50%)
);
}
/* 使用命名颜色可以实现相同的效果 */
.hsl-named-longer {
background: linear-gradient(to right in hsl longer hue, orange, yellow);
}
/* 对于不支持插值模式的浏览器 */
.fallback {
background: linear-gradient(to right, blue, red);
}
CSS Colors Module Level 4 中描述的大部分语法都在最新版本的 Chrome 和 Safari 中得到支持,而颜色函数的支持也将在 Firefox 113 中发布。在上述示例中指定线性渐变中的颜色空间和插值模式在 Chrome 和 Safari 中受支持,但是在 Firefox 中还没有支持。
CSS Color Module Level 5 包含了一个 color-mix()
函数,它可以使用指定的权重混合两种颜色,此函数已在多个浏览器中得到支持。 在 color()
函数中,将能够使用使用 color(--my-color-space 0 0 0)
定义的自定义颜色空间,该颜色空间使用 @color-profile
规则从外部文件加载。
.plum-pink-mix {
color: color-mix(in lch, plum, pink);
}
/* 自定义颜色空间 */
@color-profile --example-color-space {
src: url("https://example.org/my-color-profile.icc");
}
.header {
background-color: color(--example-color-space 10% 20% 30%);
}
[1]
CSS Colors Module Level 4: https://www.w3.org/TR/css-color-4/
[2]
https://developer.mozilla.org/en-US/blog/css-color-module-level-4/