本文档是高清 CSS 颜色指南的一部分。
CSS 颜色 4 概述了 CSS 和颜色方面的许多新功能和工具。以下 Codepen 会同时显示所有新旧颜色语法:
阅读经典颜色空间回顾。
级别 4 规范引入了 12 个用于查询颜色的新颜色空间,而之前分享的 7 种新色域已进一步增加:
探索全新的网页颜色空间
以下颜色空间提供的色域比 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 引入了访问 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 为正值时,添加红色,当低于 0 时添加绿色。如果 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 年开始支持在网页中使用 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 是向超高清电视(超高清电视)迈进的一部分,提供适合用于 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 推出了一个由 Erik Kennedy 创建的渐变工具,可为您计算其他颜色停止点,以帮助您避免死区,即使是在容易受此影响的颜色空间中。使用此参数,传递第一个示例中的相同颜色,但将颜色插值更改为 HSL,会生成以下内容:
linear-gradient(90deg, #94e99c, #99e789, #ace67d, #c4e472, #e2e366, #e2bf5a, #e1934e, #e06242);
使用引导停止点时,插值不再是直线,而是在死区附近呈现出曲线,这有助于保持饱和度,从而使渐变效果更加生动。
虽然该工具非常出色,但如果您可以直接在 CSS 中实现类似或更大的控制呢?
指定颜色插值
在颜色 4 中,添加了控制色调插值策略的功能,是规避 (:wink:) 死区的新方式。考虑一个色调角度,并考虑只改变角度的 2 级渐变,例如,色调从 140deg
转换到 240deg
。
色调插值更短与更长
渐变默认采用它可以采用的 shorter
路线,除非您指定其采用 longer
路线。色调插值选项用于指示角度旋转,例如告诉用户左转而不是右转(嘿,Zoolander):
在色相插值距离示例中,系统会模拟短路径和长路径来说明差异。短距离之间的色相越少,因为它经过的距离最少,而长距离经过了更多的色相。
增加与减少色相插值
颜色 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%)
);
}
为了结束色相插值,下面提供了一个有趣的游乐场,您可以在其中更改 2 个颜色停止点之间的色调,并查看色调插值选择的效果以及颜色空间如何改变渐变结果。效果可以截然不同;就颜色工具条而言,四个新技巧就这么简单。
不同颜色空间中的渐变
每种颜色空间都具有独特的形状和颜色排列方式,因此会产生不同的渐变。在下面的示例中,您将了解每种颜色空间是如何以不同方式处理的,尤其是在蓝色到白色时。请注意,有多少个颜色的中间部分变成了紫色;这称为插值期间的色相偏移。
这些空间中的一些渐变比其他渐变更鲜艳,或者它们在死区中的流动更少。与为了便于用户编写颜色而优化的空间(例如 hwb()
)不同,lab
等空间以针对饱和度进行优化的方式将颜色打包在一起。
.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));
}
上面的演示虽然结果很细微,但从实验结果可以看出,插值方法较为一致。不过,Labs 的语法不好阅读,但来自 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 迁移,作者:Andrey Sitnik
- Color Formats,作者:Josh W. 科梅
- OK, OKLCH(作者:Chris Coyier)
后续步骤
现在,您已经熟悉了新的颜色空间和工具,接下来可以迁移到高清颜色了。
更加生动、一致的操作和插值,从整体上为用户提供更加丰富多彩的体验。
请阅读该指南,了解更多颜色资源。