本文档是高清 CSS 颜色指南的一部分。
CSS 颜色 4 概述了一系列适用于 CSS 和颜色的新功能和工具。以下 Codepen 展示了所有新旧颜色语法:
阅读传统颜色空间的回顾。
第 4 级规范引入了 12 个用于查找颜色的新色彩空间,比之前分享的 7 个新色域多了 5 个:
了解新的 Web 颜色空间
以下色彩空间提供的色域比 sRGB 更广。display-p3 颜色空间提供的颜色数量几乎是 RGB 的两倍,而 Rec2020 提供的颜色数量几乎是 display-p3 的两倍。颜色太多了!
color()
函数
新的 color()
函数可用于使用 R、G 和 B 通道指定颜色的任何颜色空间。color()
首先接受一个颜色空间参数,然后接受一系列 RGB 通道值,以及可选的某些 Alpha 值。
您会发现许多新色彩空间都使用此函数,因为如果使用 rgb
、srgb
、hsl
、hwb
等专用函数,会导致函数列表越来越长,因此将色彩空间作为参数会更方便。
优点
- 用于访问使用 RGB 通道的颜色空间的归一化空间。
- 可扩展到任何基于 RGB 的广色域颜色空间。
缺点
- 不适用于 HSL、HWB、LCH、okLCH 或 okLAB
.valid-css-color-function-colors {
--srgb: color(srgb 1 1 1);
--srgb-linear: color(srgb-linear 100% 100% 100% / 50%);
--display-p3: color(display-p3 1 1 1);
--rec2020: color(rec2020 0 0 0);
--a98-rgb: color(a98-rgb 1 1 1 / 25%);
--prophoto: color(prophoto-rgb 0% 0% 0%);
--xyz: color(xyz 1 1 1);
}
通过 color() 使用 sRGB
此色彩空间提供与 rgb()
相同的功能。此外,它还提供介于 0 到 1 之间的小数,使用方式与 0% 到 100% 完全相同。
优点
- 几乎所有显示屏都支持此颜色空间的范围。
- 设计工具支持。
缺点
.valid-css-srgb-colors {
--percents: color(srgb 34% 58% 73%);
--decimals: color(srgb .34 .58 .73);
--percents-with-opacity: color(srgb 34% 58% 73% / 50%);
--decimals-with-opacity: color(srgb .34 .58 .73 / .5);
/* empty */
--empty-channels-black: color(srgb none none none);
--empty-channels-black2: color(srgb);
}
通过 color() 实现线性 sRGB {#linear-srgb}
这种 RGB 的线性替代方案可提供可预测的通道强度。
优点
- 直接访问 RGB 通道,非常适合游戏引擎或灯光秀等用途。
缺点
- 感知上不线性。
- 黑白图片会打包在边缘。
.valid-css-srgb-linear-colors {
--percents: color(srgb-linear 34% 58% 73%);
--decimals: color(srgb-linear .34 .58 .73);
--percents-with-opacity: color(srgb-linear 34% 58% 73% / 50%);
--decimals-with-opacity: color(srgb-linear .34 .58 .73 / .5);
/* empty */
--empty-channels-black: color(srgb-linear none none none);
--empty-channels-black2: color(srgb-linear);
}
我们稍后会详细介绍渐变,但现在先快速看一下 srgb
和 linear-srgb
黑到白的渐变,以便说明它们之间的区别:
LCH
LCH 引入了语法,以访问 RGB 色域之外的颜色。它也是首个可让您非常轻松地为显示屏创建超出色域的颜色。这是因为任何 CIE 空间颜色(lch、oklch、lab、oklab)都可以表示人类可见的整个颜色光谱。
此颜色空间以人眼视觉为模板,并提供用于指定这些颜色及更多颜色的语法。LCH 通道分别是亮度、色相和色调。色相是角度,如 HSL 和 HWB 中所示。亮度是一个介于 0 到 100 之间的值。这是一种特殊的“感知线性”轻盈感,以人为本。色度与饱和度类似;其范围介于 0 到 230 之间,但在技术上没有上限。
优点
- 由于在感知上是线性的(在大多数情况下),因此可预测颜色处理结果(请参阅 oklch)。
- 使用熟悉的渠道。
- 通常采用鲜艳的渐变色。
缺点
- 容易超出色域。
- 在极少数情况下,渐变可能需要调整中间点,以防止色相偏移。
.valid-css-lch-colors {
--percent-and-degrees: lch(58% 32 241deg);
--just-the-degrees: lch(58 32 241deg);
--minimal: lch(58 32 241);
--percent-opacity: lch(58% 32 241 / 50%);
--decimal-opacity: lch(58% 32 241 / .5);
/* chromaless and hueless */
--empty-channels-white: lch(100 none none);
--empty-channels-black: lch(none none none);
}
实验室
另一种用于访问 CIE 色域的颜色空间,同样具有感知线性亮度 (L) 维度。LAB 中的 A 和 B 代表人眼色彩感知的独特轴:红-绿轴和蓝-黄轴。为 A 赋予正值时,它会添加红色;为 A 赋予负值时,它会添加绿色。为 B 指定正值时,系统会添加黄色;负值则会添加蓝色。
优点
- 感知上一致的渐变。
- 高动态范围。
缺点
- 可能会出现色相偏移。
- 在读取值时,难以手动编写或猜测颜色。
.valid-css-lab-colors {
--percent-and-degrees: lab(58% -16 -30);
--minimal: lab(58 -16 -30);
--percent-opacity: lab(58% -16 -30 / 50%);
--decimal-opacity: lab(58% -16 -30 / .5);
/* chromaless and hueless */
--empty-channels-white: lab(100 none none);
--empty-channels-black: lab(none none none);
}
OKLCH
此色彩空间是对 LCH 的校正。与 LCH 一样,(L) 仍然表示感知线性亮度,C 表示色度,H 表示色相。
如果您使用过 HSL 或 LCH,就会发现此界面很熟悉。在色轮上为 H 选择一个角度,通过调整 L 来选择亮度或暗度,但此时我们得到的是色度,而不是饱和度。它们非常相似,但对亮度和色相的调整通常是成对进行的,否则很容易要求获得超出目标色域的高色相颜色。
优点
- 使用蓝色和紫色色调时,不会出现意外。
- 感知上线性亮度。
- 使用熟悉的渠道。
- 高动态范围。
- 采用 Evil Martians 提供的现代颜色选择器。
缺点
- 容易超出色域。
- 新兴且相对未开发。
- 颜色选择器较少。
.valid-css-oklch-colors {
--percent-and-degrees: oklch(64% .1 233deg);
--just-the-degrees: oklch(64 .1 233deg);
--minimal: oklch(64 .1 233);
--percent-opacity: oklch(64% .1 233 / 50%);
--decimal-opacity: oklch(64% .1 233 / .5);
/* chromaless and hueless */
--empty-channels-white: oklch(100 none none);
--empty-channels-black: oklch(none none none);
}
OKLAB
此聊天室是对 LAB 的纠正。 它还被声称为针对图片处理质量进行了优化的空间,对于 CSS 来说,这意味着渐变和颜色函数操作质量。
优点
- 动画和插值的默认空间。
- 感知上线性亮度。
- 不会像 LAB 那样出现色相偏移。
- 感知上一致的渐变。
缺点
- 新兴且相对未开发。
- 颜色选择器较少。
.valid-css-oklab-colors {
--percent-and-degrees: oklab(64% -.1 -.1);
--minimal: oklab(64 -.1 -.1);
--percent-opacity: oklab(64% -.1 -.1 / 50%);
--decimal-opacity: oklab(64% -.1 -.1 / .5);
/* chromaless and hueless */
--empty-channels-white: oklab(100 none none);
--empty-channels-black: oklab(none none none);
}
显示屏 P3
自 2015 年 Apple 在 iMac 上支持 Display P3 色域和色彩空间以来,它们就广受欢迎。此外,Apple 自 2016 年起就通过 CSS 在网页中支持 display-p3,比任何其他浏览器都早了 5 年。如果您使用的是 sRGB,那么在将样式转换为更高动态范围时,可以先从这个色彩空间着手。
优点
- 出色的支持,被视为 HDR 显示屏的基准。
- 比 sRGB 多出 50% 的颜色。
- 开发者工具提供了一个出色的颜色选择器。
缺点
- 最终将被 Rec2020 和 CIE 色彩空间所取代。
.valid-css-display-p3-colors {
--percents: color(display-p3 34% 58% 73%);
--decimals: color(display-p3 .34 .58 .73);
--percent-opacity: color(display-p3 34% 58% 73% / 50%);
--decimal-opacity: color(display-p3 .34 .58 .73 / .5);
/* chromaless and hueless */
--empty-channels-black: color(display-p3 none none none);
--empty-channels-black2: color(display-p3);
}
Rec2020
Rec2020 是朝着 UHDTV(超高清电视)迈进的一步,可提供丰富的色彩,供 4K 和 8K 媒体使用。Rec2020 是另一种基于 RGB 的色域,比 display-p3 更大,但在消费者中并不像 Display P3 那样常见。
优点
- 超高清色彩。
缺点
- 在消费者中尚不普遍。
- 通常不出现在手持设备或平板电脑中。
.valid-css-rec2020-colors {
--percents: color(rec2020 34% 58% 73%);
--decimals: color(rec2020 .34 .58 .73);
--percent-opacity: color(rec2020 34% 58% 73% / 50%);
--decimal-opacity: color(rec2020 .34 .58 .73 / .5);
/* chromaless and hueless */
--empty-channels-black: color(rec2020 none none none);
--empty-channels-black2: color(rec2020);
}
A98 RGB {#a98-rgb}
A98 RGB 是 Adobe 1998 RGB 的缩写,由 Adobe 创建,可呈现 CMYK 打印机可实现的大多数颜色。它提供的颜色比 sRGB 多,尤其是在青色和绿色色调方面。
优点
- 比 sRGB 和 Display P3 颜色空间更大。
缺点
- 不是数字设计师常用的空间。
- 很少有人会从 CMYK 移植调色板。
.valid-css-a98-rgb-colors {
--percents: color(a98-rgb 34% 58% 73%);
--decimals: color(a98-rgb .34 .58 .73);
--percent-opacity: color(a98-rgb 34% 58% 73% / 50%);
--decimal-opacity: color(a98-rgb .34 .58 .73 / .5);
/* chromaless and hueless */
--empty-channels-black: color(a98-rgb none none none);
--empty-channels-black2: color(a98-rgb);
}
ProPhoto RGB
此宽色域空间由柯达创建,具有独特的超宽范围主色,并且在更改亮度时色相偏移极小。它还声称涵盖了 100% 的真实表面颜色,如 Michael Pointer 在 1980 年记录的那样。
优点
- 更改亮度时,色相偏移极小。
- 鲜艳的原色。
缺点
- 其中约 13% 的颜色是虚构的,也就是说,这些颜色不在人眼可见的光谱范围内。
.valid-css-prophoto-rgb-colors {
--percents: color(prophoto-rgb 34% 58% 73%);
--decimals: color(prophoto-rgb .34 .58 .73);
--percent-opacity: color(prophoto-rgb 34% 58% 73% / 50%);
--decimal-opacity: color(prophoto-rgb .34 .58 .73 / .5);
/* chromaless and hueless */
--empty-channels-black: color(prophoto-rgb none none none);
--empty-channels-black2: color(prophoto-rgb);
}
XYZ、XYZ-d50、XYZ-d65
CIE XYZ 色彩空间涵盖了普通视力人士可见的所有颜色。因此,它被用作其他色彩空间的标准参考。Y 是亮度,X 和 Z 是给定 Y 亮度范围内的可能色度。
d50 和 d65 之间的区别在于白点,其中 d50 使用 d50 白点,d65 使用 d65 白点。
关键字:白点是色彩空间的属性,是指色彩空间中存在的真白色。对于电子屏幕,D65 是最常见的白点,是 6500 开尔文的简称。在颜色转换中,白点匹配非常重要,这样颜色温度(暖色或冷色)就不会受到影响。
优点
- 线性光照访问有许多实用场景。
- 非常适合进行实际颜色混合。
缺点
- 与 lch、oklch、lab 和 oklab 不同,在感知上并不线性。
.valid-css-xyz-colors {
--percents: color(xyz 22% 26% 53%);
--decimals: color(xyz .22 .26 .53);
--percent-opacity: color(xyz .22 .26 .53 / 50%);
--decimal-opacity: color(xyz .22 .26 .53 / .5);
/* chromaless and hueless */
--empty-channels-black: color(xyz none none none);
--empty-channels-black2: color(xyz);
}
.valid-css-xyz-d50-colors {
--percents: color(xyz-d50 22% 26% 53%);
--decimals: color(xyz-d50 .22 .26 .53);
--percent-opacity: color(xyz-d50 .22 .26 .53 / 50%);
--decimal-opacity: color(xyz-d50 .22 .26 .53 / .5);
/* chromaless and hueless */
--empty-channels-black: color(xyz-d50 none none none);
--empty-channels-black2: color(xyz-d50);
}
.valid-css-xyz-d65-colors {
--percents: color(xyz-d65 22% 26% 53%);
--decimals: color(xyz-d65 .22 .26 .53);
--percent-opacity: color(xyz-d65 .22 .26 .53 / 50%);
--decimal-opacity: color(xyz-d65 .22 .26 .53 / .5);
/* chromaless and hueless */
--empty-channels-black: color(xyz-d65 none none none);
--empty-channels-black2: color(xyz-d65);
}
自定义色彩空间
CSS 颜色 5 规范还提供了一种向浏览器传授自定义色彩空间的方法。这是一份 ICC 色彩特性文件,用于告知浏览器如何解析颜色。
@color-profile --foo {
src: url(path/to/custom.icc);
}
加载完成后,使用 color()
函数访问此自定义配置文件中的颜色,并为其指定色相值。
.valid-css-color-from-a-custom-profile {
background: color(--foo 1 0 0);
}
颜色插值
从一种颜色过渡到另一种颜色在动画、渐变和颜色混合中很常见。此过渡通常指定为起始颜色和结束颜色,浏览器应在两者之间进行插值。在本例中,插值意味着生成一系列中间颜色,以实现平滑的过渡,而不是瞬间过渡。
对于渐变,插值是沿着形状的一系列颜色。动画是指一段时间内一系列颜色。
@keyframes bg {
0%, 100% {
background: orange;
}
25% {
background: magenta;
}
50% {
background: lime;
}
75% {
background: cyan;
}
}
.circle {
animation: bg 5s ease-in-out infinite;
}
使用渐变时,中间颜色会同时显示:
颜色插值的新变化
随着新色域和色彩空间的添加,我们还新增了一些插值选项。将颜色 in hsl
从蓝色过渡到白色会产生与 sRGB 截然不同的结果。
.classic-gradient-in-srgb {
background: linear-gradient(to right, blue, white);
}
.new-gradient-in-hsl {
background: linear-gradient(in hsl to right, blue, white);
}
那么,如果您从一个色彩空间的颜色过渡到完全不同的色彩空间的颜色,会发生什么情况:
.gradient {
/* oklab will be the common space */
background: linear-gradient(to right, lch(29.6 131 301), hsl(330 100% 50%));
}
.lch {
/* lch is specified */
background: linear-gradient(in lch to right, lch(29.6 131 301), hsl(330 100% 50%));
}
幸运的是,Color 4 规范提供了有关如何处理这些跨颜色空间插值的浏览器说明。对于 .gradient
,浏览器会注意到不同的颜色空间,并使用默认颜色空间 oklab
。
您可能会认为浏览器会使用 lch 作为颜色空间,因为它是第一个颜色,但事实并非如此。因此,我会显示第二个比较渐变 .lch
。.lch
渐变是 lch 色彩空间中的渐变。
16 位颜色减少了条纹
在此颜色更改之前,所有颜色都保存在一个 32 位整数中,以表示红色、绿色、蓝色和 Alpha 这四个通道。即每个通道 8 位,可显示 2^ 24 种颜色(忽略 Alpha 通道)。2 ^ 24 = 16,777,216,即“数百万种颜色”。
完成此颜色处理后,四个 16 位浮点值,每个通道都有自己的浮点值,而不是归为一组。这总共是 64 位数据,因此可产生的颜色数量远远超过数百万种。
必须完成此工作才能支持高清色彩。这会增加可存储的颜色信息量,这有一个不错的副作用,即浏览器在渐变中可以使用更多颜色。
渐变条纹是指颜色不足以创建平滑的渐变,并且出现颜色“条纹”。升级到更高分辨率的颜色后,条纹问题得到了显著缓解。
控制插值
两点之间的最短距离始终是直线。使用颜色插值时,浏览器默认采用捷径。假设 HSL 颜色圆柱中存在两个点。渐变色是沿着两点之间的线条获得颜色步骤的。
linear-gradient(to right, #94e99c, #e06242)
上图中的渐变线条从绿色直接过渡到红色,并穿过色彩空间的中心。虽然上述说明有助于初步了解,但实际情况并非如此。以下 Codepen 中显示了渐变效果,中间显然不是白色,如模拟演示所示。
不过,渐变的中间区域已失去活力。这是因为最鲜艳的颜色位于色彩空间形状的边缘,而不是位于插值经过的中心。这通常称为“死区”。您可以通过以下几种方法解决或规避此问题。
指定更多渐变停止点以避免出现死区
目前,避免出现死区的方法是在渐变中添加额外的颜色停止点,以有意引导插值保持在色彩空间的鲜艳范围内。这实际上是一种权宜之计,因为额外的停止点有助于它绕过死区。
Erik Kennedy 创建了一个渐变工具,可为您计算其他色阶,帮助您避免出现死区,即使在容易出现死区的颜色空间中也是如此。使用它,传递第一个示例中的相同颜色,但将颜色插值更改为 HSL,会生成以下结果:
linear-gradient(90deg, #94e99c, #99e789, #ace67d, #c4e472, #e2e366, #e2bf5a, #e1934e, #e06242);
借助引导式停止点,插值不再是一条直线,而是看起来会围绕死区弯曲,有助于保持饱和度,从而产生更鲜艳的渐变效果。
虽然该工具非常实用,但如果您可以直接通过 CSS 获得类似或更强的控制功能,该怎么办?
引导颜色插值
在 Color 4 中,添加了控制色相插值策略的功能,这是解决死区问题的新方法 (:wink:)。考虑一下色相角度,并考虑一个仅更改角度的 2 个停止点渐变,例如从 140deg
到 240deg
的色相变化。
色相插值时间较短与较长
除非您指定采用 longer
路线,否则渐变色默认会采用可用的 shorter
路线。色相插值选项用于控制角度旋转,就像告诉某人向左转而不是向右转一样(呵呵,Zoolander):
在色相插值距离示例中,我们模拟了短路径和长路径,以说明二者之间的差异。短距离之间色相较少,因为它经过的距离尽可能短,而长距离经过的色相较多。
增加色相插值与减少色相插值
Color 4 中还有另外两种色相插值策略,但它们仅适用于圆柱形色彩空间。继续使用前面示例中的两种颜色,现在的视觉效果展示了“增大”和“缩小”的运作方式。
上面的 Codepen 使用 ColorJS 演示了预期结果。若要在不使用 JavaScript 库的情况下实现相同的效果,您需要编写以下 CSS:
.longer-hue-interpolation-in-css {
background: linear-gradient(
to right in hsl longer hue,
hsl(180deg 100% 75%),
hsl(240deg 100% 75%)
);
}
.decreasing-hue-interpolation-in-css {
background: linear-gradient(
to right in hsl decreasing hue,
hsl(180deg 100% 75%),
hsl(240deg 100% 75%)
);
}
为了结束对色相插值的介绍,我们为您准备了一个有趣的 Playground,您可以在其中更改 2 个色阶之间的色相,并查看色相插值选项的效果,以及色彩空间如何改变渐变结果。效果可能截然不同;不妨将这四种方法视为刚刚加入您颜色工具箱的新技巧。
不同色彩空间中的渐变
由于每个色彩空间都有自己独特的形状和颜色排列方式,因此会产生不同的渐变效果。在以下示例中,请查看每种色彩空间如何以不同的方式处理这一点,尤其是在蓝色到白色之间。请注意中间有多少个像素变成了紫色;这称为插值期间的色相偏移。
这些空间中的某些渐变色比其他渐变色更鲜艳,或者在死区中穿行较少。lab
等聊天室会以针对饱和度进行了优化的方式将颜色打包在一起,而 hwb()
等聊天室则会以针对人类编写颜色进行了优化的方式打包颜色。
.hwb {
background: linear-gradient(to right, hwb(250 10% 10%), hwb(150 10% 10%));
}
.lab {
background: linear-gradient(to right, lab(30 59.4 -96), lab(80 -64 36.2));
}
虽然上述演示的结果不明显,但确实显示了与实验室相比,插值更为一致。不过,lab 的语法不易读懂,其中包含一些从 rgb 或 hsl 转换过来的负数,这些负数非常陌生。好消息是,我们可以使用 hwb 来获得熟悉的语法,但要求将渐变完全在另一个颜色空间(例如 oklab)中插值。
.hwb {
background: linear-gradient(in hwb to right, hwb(250 10% 10%), hwb(150 10% 10%));
}
.lab {
background: linear-gradient(in oklab to right, hwb(250 10% 10%), hwb(150 10% 10%));
}
此示例使用 hwb 中的相同颜色,但指定了颜色空间以对 hwb 或 oklab 进行插值。hwb
非常适合实现高饱和度,但可能会出现死区或亮点(请参阅上例中的青绿色热点)。oklab 非常适合实现感知上线性的饱和度渐变。这项功能非常有趣,您可以试用几种不同的色彩空间,看看哪种渐变最适合您。
下面的 Codepen 实验了渐变和色彩空间,并混合了匹配策略,以探索各种可能性。即使是从黑色到白色的过渡,在每个颜色空间中也不同!
色域限制
在某些情况下,颜色可能会请求色域之外的内容。请考虑以下颜色:
rgb(300 255 255)
rgb
颜色空间中颜色通道的最大值为 255
,但此处为红色指定了 300
。会出现什么情况?色域限制。
钳制是指直接移除额外信息。300
在颜色引擎内部会变为 255
。颜色现在已被限制在其范围内。
选择色彩空间
许多人了解这些色彩空间及其影响后,会感到不知所措,并想知道应该选择哪个“选项”。根据我的研究和经验,我认为没有一种颜色空间适用于所有任务。每种广告素材都有能带来预期成效的时刻。
如果有一个最佳聊天室,我们就不会推出这么多新聊天室。
不过,我可以说 CIE 色彩空间(lab
、oklab
、lch
和 oklch
)是我入门的起点。如果测试结果不符合我的预期,我会测试其他聊天室。对于混合颜色和创建渐变,我同意选择 oklab
作为默认规范。对于颜色系统和整体界面颜色,我喜欢 oklch
。
以下几篇文章介绍了一些用户在这些新颜色空间和功能的加持下,更新了自己的配色策略。例如,Andrey Sitnik 全力投入 oklch
,也许他们能说服您也这样做:
- CSS 中的 OKLCH:为何从 RGB 和 HSL 改用 OKLCH(作者:Andrey Sitnik)
- 颜色格式 作者:Josh W. Comeau
- Chris Coyier 撰写的 OK, OKLCH
后续步骤
现在,您已经熟悉了新的色彩空间和工具,可以迁移到高清色彩了。
色彩更鲜艳,操作和插值更一致,总体上为用户提供更丰富多彩的体验。
如需详细了解颜色资源,请参阅该指南。