CSS color functions, gradients, color spaces title. What's new in CSS Colors Module Level 4 subtitle. A vibrant gradient behind artwork of a laptop and keyboard

CSS 颜色(Level 4)中的新函数、渐变和色相

阅读时间 9 分钟

越来越多的浏览器开始支持 CSS Colors Module Level 4 规范中定义的功能,该规范包含了在 CSS 中操作和显示颜色的多种方法。让我们一起来了解色彩空间、如何在 CSS 中定义颜色、CSS Colors Module Level 4 的新特性,以及你如何将这些颜色函数和特性运用到你的项目中。

理解色彩空间

要理解 CSS 中颜色的描述方式,快速了解色彩空间会有所帮助。色彩空间是基于定义的 颜色模型 对颜色进行分组的系统。色彩空间提供了一种清晰一致的描述颜色的方式,并且可以在不改变外观的情况下将一种颜色转换为另一种色彩空间。

在 CSS Colors Module Level 4 之前,CSS 中的颜色是在 RGB(红、绿、蓝)色彩空间和 色域(颜色的总范围)中定义的。

A cube representing the RGB color space with red, green, and blue at the corners

随着 HSL(色相、饱和度、亮度)支持的加入,你可以使用与 RGB 模型相同的模型来定义颜色,但改用色相、饱和度和亮度。我们将在下一节中更详细地介绍 RGB 和 HSL。

在 CSS 中定义 RGB 颜色

要在 RGB 色彩空间中创建颜色,你需要以不同的方式混合红、绿、蓝这三种原色,以获得所需的结果。你可以将其想象成一个立方体中的点坐标,其中每个轴代表一种原色。

css
.red {
  color: rgb(255 0 0);
}
.green {
  color: rgb(0 255 0);
}
.blue {
  color: rgb(0 0 255);
}
/* yellow is a mix of red and green */
.yellow {
  color: rgb(255 255 0);
}
/* cyan is a mix of green and blue */
.cyan {
  color: rgb(0 255 255);
}

在 CSS 中定义 RGB 颜色时,你可以选择使用颜色的关键字(如 redblue)、十六进制值(#ff0000)或 rgb() 函数 来定义红、绿、蓝的值,如上面的示例所示。

根据 CSS Colors Module Level 4,你不再需要使用 rgba() 来定义带 alpha 通道的 RGB 颜色,因为 rgb() 支持用斜杠(/)分隔的 alpha 值,如下所示。此示例演示了如何使用关键字、十六进制值和 rgb() 函数来定义相同的颜色,其中还包括定义不透明度的示例。

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

使用 HSL 选择色相

对 CSS 引入 HSL(CSS Colors Level 3) 的支持受到了许多开发者的欢迎,因为根据 色轮 选择色相更加直观。我们可以使用 conic-gradient() 函数和 hsl() 函数来创建一个色轮。制作这个渐变循环遍历所有色相的技巧在下面的 色相插值 部分有描述。

css
#color-wheel {
  border-radius: 50%;
  background: conic-gradient(
    in hsl longer hue,
    hsl(0deg 100% 50%),
    hsl(360deg 100% 50%)
  );
}
/* For browsers that don't support hue interpolation methods */
@supports not (background: conic-gradient(in hsl longer hue)) {
  #color-wheel {
    background: conic-gradient(red, yellow, green, cyan, blue, magenta, red);
  }
}
html
<div id="color-wheel"></div>

如果我们结合这两个代码片段,就可以创建一个循环遍历 RGB 色彩空间中所有可用色相的色轮。

hsl() 函数的工作方式与 rgb() 函数类似,但接受色轮上的色相角度以及饱和度和亮度值。与 rgb() 一样,你可以为 hsl() 添加 alpha 通道以实现透明度(或不透明度),这使得 hsla()rgba() 一样成为遗留函数。

css
.red-hsl {
  color: hsl(0 100% 50%);
}
.green-hsl {
  color: hsl(120 100% 50%);
}
/* Make the color 50% opaque */
.green-hsl {
  color: hsl(120 100% 50% / 0.5);
}

HSL 函数的另一个便利之处在于,你可以通过改变饱和度和亮度来制作颜色的变体,而不必尝试计算 RGB 值。例如,如果你为网站主题选择了一种特定颜色,你可以修改该颜色的饱和度和亮度来创建一种仍然符合主题的二级颜色。这在下面进行了说明。

css
.button {
  color: hsl(200 100% 70%);
}
/* A darker version of the button color */
.button--secondary {
  color: hsl(200 100% 50%);
}
/* Lower saturation makes the button less vibrant */
.button--inactive {
  color: hsl(200 50% 70%);
}

CSS Colors Module Level 4 有哪些新特性?

此规范版本添加了许多使用不同颜色表示方式的新颜色函数,它们都允许你使用色相、亮度、饱和度等属性来指定颜色。新的颜色函数使你能够使用 RGB 色域之外的更鲜艳的颜色,因此在支持的显示器上可用颜色范围更广。

支持更多色彩空间和色域

随着对其他空间和色域的支持,你不再局限于在 RGB 色彩空间中描述颜色;你现在可以使用 Display P3、CIELAB、Oklab 色彩空间。让我们快速了解一下这些意味着什么。

Display P3 使用 P3 色域,表示比 sRGB(标准 RGB)更宽的颜色范围。它对于现代显示器使用的更鲜艳的颜色非常有用。但是,你需要注意为不支持它的设备的用户提供回退方案。

CIELAB 是一个均匀色彩空间(UCS),它根据人眼对颜色的感知来定义颜色。该模型的主要目的是使颜色空间中两点之间的相同颜色距离在观众看来同样不同。

Oklab 是一个较新的色彩空间,它使用与 CIELAB 相同的模型结构,但通过“对视觉上相似的颜色数据集进行数值优化”而创建,因此其值旨在比 CIELAB 更准确。

CIELAB 和 Oklab 色彩空间不是用轮子、圆柱体或立方体来表示,而是可以表示为看起来像这样的三维空间。

A three-dimensional representation of the CIELAB color space with points showing the location of some colors in the space.

颜色新函数式表示法

新的颜色函数有助于描述我们在上一节中看到的色彩空间中的值。让我们看一下每个新函数及其工作方式。

lab() 函数式表示法使用亮度、红/绿度(red/green-ness)和黄/蓝度(yellow/blue-ness)沿色彩空间的“a”和“b”轴来描述 CIELAB 颜色。

css
.lab-red {
  color: lab(87.6 125 104);
}
.lab-green {
  color: lab(87.8 -79 81);
}

lch() 函数式表示法使用亮度、色度和色相来描述 CIELAB 颜色。色相是色轮上表示颜色的角度。

css
.lch-red {
  color: lch(54.3 107 40.9deg);
}
.lch-green {
  color: lch(87.8 113 134deg);
}

oklab() 函数式表示法使用亮度、红/绿度(red/green-ness)和黄/蓝度(yellow/blue-ness)沿 Oklab 色彩空间的“a”和“b”轴来描述 Oklab 颜色。

css
.oklab-red {
  color: oklab(0.63 0.22 0.13);
}
.oklab-green {
  color: oklab(0.87 -0.2 0.18);
}

oklch() 函数式表示法使用亮度、色度和色相来描述 Oklab 颜色。

css
.oklch-red {
  color: oklch(0.93 0.39 28deg);
}
.oklch-green {
  color: oklch(0.87 0.29 142deg);
}

除了新的色彩空间之外,还有一个用于 HWB 颜色的 hwb() 函数式表示法,它使用色相、白度和黑度来定义颜色。HWB 使用 RGB 色彩空间,与 HSL 类似,但考虑的是白度和黑度而不是饱和度和亮度。

css
.hwb-red {
  color: hwb(0deg 0% 0%);
}
.hwb-light-red {
  color: hwb(0deg 30% 0%);
}
.hwb-dark-red {
  color: hwb(0deg 0% 30%);
}
/* Cycle through the color wheel */
.hwb-green {
  color: hwb(120deg 0% 0%);
}
.hwb-blue {
  color: hwb(240deg 0% 0%);
}

最后,有一个 color() 函数式表示法,它允许你在预定义的色彩空间中指定颜色。

css
.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() 函数式表示法与媒体查询结合使用,以指定回退色彩空间。

css
.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 值。

css
/* old syntax */
rgb(255, 0, 0);
hsl(0, 100%, 50%);

/* new syntax */
rgb(255 0 0);
hsl(0 100% 50%);

/* new syntax with alpha channels */
rgb(255 0 0 / 0.5);
hsl(0 100% 50% / 0.5);

所有新函数都使用上述类型的语法,值之间没有分隔逗号,并使用斜杠将 alpha 通道与颜色值分隔开。

色相插值

随着新的色彩空间出现,其中一个好处是可以在不深入研究色彩科学的情况下创建渐变。插值是指在两个已知值之间计算一个或多个值,因此如果你有一个从红色到蓝色的渐变,插值就是你计算红色和蓝色之间的颜色范围的方式。在创建 linear-gradient() 或类似的 CSS 渐变时,你可以使用 in(表示插值)后跟渐变的色彩空间。

css
.hsl {
  background: linear-gradient(in hsl, blue, red);
}

比较不同色彩空间中的渐变

我们可以创建一个快速示例来比较不同色彩空间中的渐变。在下面的示例中,我们在标准 RGB 色彩空间中有一个从蓝色到红色的渐变,然后在不同的色彩空间中有相同的渐变。

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

这让我们对不同色彩空间中的渐变外观以及它们各自的插值工作方式有了很好的了解。

在渐变中使用色相插值模式

有一些 插值模式 可以控制在具有色相角度的色彩空间中,色相应该沿着色轮的哪个方向进行插值。

html
<div class="hsl in-function">
  <p>HSL</p>
</div>
<div class="hsl-named in-function">
  <p>HSL named</p>
</div>

<div class="hsl-longer in-function">
  <p>HSL (longer)</p>
</div>
<div class="hsl-named-longer in-function">
  <p>HSL named (longer)</p>
</div>

<div class="fallback">
  <p>Standard fallback</p>
</div>
css
/* From 39deg to 60deg, taking the shortest path around the color wheel */
.hsl {
  background: linear-gradient(
    to right in hsl,
    hsl(39deg 100% 50%),
    hsl(60deg 100% 50%)
  );
}
/* We can also use named colors */
.hsl-named {
  background: linear-gradient(to right in hsl, orange, yellow);
}

/* This gradient cycles back through 0deg around the color wheel */
.hsl-longer {
  background: linear-gradient(
    to right in hsl longer hue,
    hsl(39deg 100% 50%),
    hsl(60deg 100% 50%)
  );
}

/* The same effect can be achieved with named colors */
.hsl-named-longer {
  background: linear-gradient(to right in hsl longer hue, orange, yellow);
}

/* For browsers that don't support interpolation modes */
.fallback {
  background: linear-gradient(to right, blue, red);
}

浏览器支持

CSS Colors Module Level 4 中描述的大部分语法在最新版本的 Chrome 和 Safari 中都得到了支持,Firefox 113 开始支持颜色函数。上面示例中的色彩空间和插值模式的指定在 Chrome 和 Safari 中得到支持,但尚未在 Firefox 中支持。你可以查看 MDN <color> 页面 以获取本文中介绍的其他功能的浏览器兼容性数据。

总结

这里快速回顾一下本文涵盖的所有重点内容:

  • 对于 RGB 色彩空间,hwb() 函数式表示法允许你使用色相、白度和黑度来指定颜色。

  • 对于 CIELAB 色彩空间,你可以使用 lab()lch() 函数式表示法。

  • 对于 Oklab(类似于 CIELAB 色彩空间但数据更新),你可以使用 oklab()oklch() 函数式表示法。

  • 对于那些想深入研究不同色彩空间的人来说,color() 允许你使用 color(srgb) 来表示标准 RGB,并使用 color(display-p3) 来表示宽色域显示器中使用的 Display P3。还有其他适合摄影师、视频专业人士和色彩科学家等专家的色彩空间。

    • color(rec2020):Rec2020 广播行业标准色彩空间
    • color(prophoto-rgb):摄影师使用的 ProPhoto RGB 色彩空间
    • color(a98-rgb):Adobe RGB 色彩空间
    • color(xyz):CIE XYZ 色彩空间,其轴使用线性光强度以更好地预测颜色混合
    • color(srgb-linear):线性化 sRGB 色彩空间

下一步是什么?

CSS Color Module Level 5 描述了一个 color-mix() 函数式表示法,它允许你使用指定的权重混合两种颜色。此函数已在多个浏览器中得到支持,因此你可以立即开始尝试,但值得关注 MDN color-mix() 页面 以获取浏览器兼容性数据。在 color() 函数中,你将能够使用通过 color(--my-color-space 0 0 0) 定义的自定义色彩空间,该自定义色彩空间使用 @color-profile 规则从外部文件加载。

css
.plum-pink-mix {
  color: color-mix(in lch, plum, pink);
}

/* Custom color space */
@color-profile --example-color-space {
  src: url("https://example.org/my-color-profile.icc");
}
.header {
  background-color: color(--example-color-space 10% 20% 30%);
}

有用资源