CSS Color 4 为网页提供了广色域颜色工具和功能:更多的颜色、操作函数和更好的渐变效果。
25 年来,
sRGB
(标准红绿蓝)一直是 CSS 渐变和颜色的唯一
色域,其中包含
rgb()
、
hsl()
和十六进制颜色等颜色空间。这是显示屏中最常见的色域功能,也是很常见的标准。我们已经
已经习惯于指定此色域内的颜色。
随着显示屏能够显示各种颜色的能力,CSS 需要通过某种方式来指定这些更广泛范围内的颜色。当前的颜色格式没有适用于广色域的语言。
如果 CSS 从未更新过,它将永远困在 90 年代的颜色范围内,被迫永远无法与图片和视频中的广色域产品保持一致。 陷阱,仅显示 人眼能看到的颜色的 30%。感谢 CSS Color Level 4 帮助我们逃脱这个陷阱;主要由 Lea Verou 和 Chris Liley 撰写。
从 Chrome 111 开始,它支持
CSS 颜色 4 色域和颜色空间;Safari 也在 2016 年就开始支持
display-p3
。CSS 现在可以支持 HD(高清)显示屏,指定高清色域的颜色,同时提供具有专精领域的颜色空间。本指南将为您介绍如何开始充分利用以下新的色彩世界。
在支持的浏览器中,有 50% 以上的颜色可供选择!您曾以为 1600 万种颜色听起来似乎有点多,等到您看看这些新空间可以呈现多少种颜色时,再看看吧。此外,请考虑所有因位深不足而导致的 带状梯度问题,这些问题也会得到解决。
除了更多颜色( 可以说是显示屏能够呈现的最鲜明的颜色)之外,新的颜色空间还为管理和创建颜色系统提供了独特的工具和方法。 例如,以前我们有 HSL 及其“lightness”渠道,它是 Web 开发者的最佳选择。现在,在 CSS 中,我们采用了 LCH 的 “感知亮度”。
此外,渐变和混合进行了一些升级:支持颜色空间、色调插值选项以及减少条带。下图显示了一些混合升级。前两种混合颜色采用 sRGB。底部两种色彩组合位于 Display p3 中。Display p3 具有更鲜艳的色彩,混合会使中间显示完全的黑白效果。其中 sRGB 看起来有点不饱和,中间的混合不是完整的黑色或白色结果。
本指南将介绍颜色的出现位置、颜色的方向,以及 CSS 如何启用和支持 Web 开发者管理颜色。
概览
颜色和网络的问题在于,CSS 尚不具备高清显示能力,而大多数人口袋里、放在口袋里或安装在墙上的显示屏都具备广色域、高清色彩。显示屏的颜色功能增长速度快于 CSS,现在 CSS 来追赶他们的步伐了。
不只是“更多颜色”而已。学完本文后,您将能够指定更多颜色、增强渐变效果,以及为每项任务选择最佳颜色空间和色域。
什么是色域?
色域表示内容的大小。短语“百万色”是关于显示屏的色域或颜色范围的说明。在下图中,我们比较了三种色域,色域越大,提供的颜色就越多。
色域也可以有名称。比如篮球、棒球、通风口咖啡杯和大杯;尺寸名称有助于人们进行沟通。了解这些色域名称有助于您沟通并快速理解一系列颜色。
本文将向您介绍七种新的色域,这些色域的范围比 sRGB 更广,并介绍它们的不同功能,以帮助您选择要使用的类型:
- sRGB
- RGB 98
- Display p3
- Rec2020
- ProPhoto
- 信息技术行业协会 (CIE)
- HVS(人类视觉色域)
人物色域
色域通常与人类视觉色域进行比较;我们认为人眼可以看到的全部颜色。HVS 通常用 色度图来描绘,如下所示:
最外层的形状是我们所看到的人类形状,内三角形是
rgb()
函数范围,也称为 sRGB 颜色空间。
正如您在上方看到的三角形,通过比较色域大小,您是否能在下方找到三角形。这是业界传达色域并进行比较的方法。
什么是颜色空间?
颜色空间是色域的排列,用于建立形状和访问颜色的方法。很多形状都是简单的 3D 形状,例如立方体或圆柱体。这种颜色排列方式决定了哪些颜色相邻,以及访问和插值颜色如何工作。
RGB 类似于矩形颜色空间,它通过指定 3 个轴上的坐标来获取颜色。HSL 是 圆柱形颜色空间,其中颜色通过色调角度和 2 个轴上的坐标进行访问
级别 4 规范引入了 12 个新的颜色空间,用于从之前共享的 7 种新色域中查找颜色:
这些是对之前可用的 4 种颜色空间的补充:
色域和颜色空间摘要
颜色空间是颜色的映射,其中色域是一系列颜色。不妨将色域视为粒子的总数量,将颜色空间视为用于容纳该范围粒子的瓶子。
这里通过互动图展示了我的意思。在此演示中,您可以指向、拖动和缩放充满颜色粒子的颜色空间。然后,更改颜色空间或颜色模型(此演示中称之为颜色模型),以查看其他空间的可视化效果。
- 使用 色域介绍一系列颜色,例如低色域或窄色域与高色域或广色域。
- 使用 颜色空间可以介绍颜色排列方式、用于指定颜色的语法、操纵颜色以及对颜色进行插值。
如何获取更多颜色、新空间和调试结果
CSS 颜色 4 概述了 CSS 和颜色方面的许多新功能和工具。首先,我们来回顾一下推出这些新功能之前的颜色阶段。然后,我们将简要介绍新的颜色空间、语法和工具。
以下 Codepen 会同时显示所有新旧颜色语法:
经典色彩空间回顾
自 2000 年代以来,您已经能够对任何接受颜色作为值的任何 CSS 属性使用以下内容:十六进制(十六进制数)、
rgb()
、
rgba()
、按名称(如
hotpink
)或关键字(如
currentColor
)。
CSS 可在 2010 年左右使用
hsl()
颜色,具体取决于您的浏览器。然后在 2017 年推出
包含 alpha 的十六进制值。最近,
hwb()
才开始获得浏览器支持。
所有这些经典颜色空间都会引用同一色域 sRGB 内的颜色。
HEX
十六进制颜色空间使用十六进制数字指定 R、G、B 和 A。 以下代码示例展示了此语法指定红色、绿色和蓝色以及不透明度的所有方式。
.valid-css-hex-colors {
/* classic */
--3-digits: #49b;
--6-digits: #4499bb;
/* hex with opacity */
--4-digits-opaque: #f9bf;
--8-digits-opaque: #ff99bbff;
--4-digits-with-opacity: #49b8;
--8-digits-with-opacity: #4499bb88;
}
RGB
RGB 颜色空间功能可直接访问红色、绿色和蓝色通道。它允许指定 0 到 255 之间的数量,或指定为 0 到 100 之间的百分比。 该语法在规范中的一些语法规范化之前就存在,因此您会看到逗号和无逗号语法。今后,将不再需要英文逗号。
.valid-css-rgb-colors {
--classic: rgb(64, 149, 191);
--modern: rgb(64 149 191);
--percents: rgb(25% 58% 75%);
--classic-with-opacity-percent: rgba(64, 149, 191, 50%);
--classic-with-opacity-decimal: rgba(64, 149, 191, .5);
--modern-with-opacity-percent: rgb(64 149 191 / 50%);
--modern-with-opacity-decimal: rgb(64 149 191 / .5);
--percents-with-opacity-percent: rgb(25% 58% 75% / 50%);
--percents-with-opacity-decimal: rgb(25% 58% 75% / 50%);
--empty-channels: rgb(none none none);
}
HSL
HSL(色相饱和度和亮度)是首批使自己面向人类语言和沟通的颜色空间之一,它提供了 sRGB 色域中的所有颜色,同时不需要您的大脑知道红色、绿色和蓝色如何相互作用。与 RGB 一样,其语法中原本也包含英文逗号,但以后便不再需要英文逗号。
.valid-css-hsl-colors {
--classic: hsl(200deg, 50%, 50%);
--modern: hsl(200 50% 50%);
--classic-with-opacity-percent: hsla(200deg, 50%, 50%, 50%);
--classic-with-opacity-decimal: hsla(200deg, 50%, 50%, .5);
--modern-with-opacity-percent: hsl(200 50% 50% / 50%);
--modern-with-opacity-decimal: hsl(200 50% 50% / .5);
/* hueless and no saturation */
--empty-channels-white: hsl(none none 100%);
--empty-channels-black: hsl(none none 0%);
}
HWB
另一个面向人类描述颜色的 sRGB 色域颜色空间是 HWB(色相、白度、黑度)。作者可以选择色调并混合使用白色或黑色以找到想要的颜色。
.valid-css-hwb-colors {
--modern: hwb(200deg 25% 25%);
--modern2: hwb(200 25% 25%);
--modern-with-opacity-percent: hwb(200 25% 25% / 50%);
--modern-with-opacity-decimal: hwb(200 25% 25% / .5);
/* hueless and no saturation */
--empty-channels-white: hwb(none 100% none);
--empty-channels-black: hwb(none none 100%);
}
探索全新的网页颜色空间
以下颜色空间提供的色域比 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
这种 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
的黑到白渐变来说明它们之间的差异:
伦敦希思罗国际机场
这篇博文的第一个空格将介绍访问 RGB 色域之外的颜色的语法!这也是首款能够轻松为显示屏创建色域色彩的先例。这是因为 任何 CIE 空间颜色(lch、oklch、lab、oklab)都能够表示完整的人类可见色谱。
此颜色空间是仿照人类视觉构建的,并提供用于指定其中任何颜色及其他颜色的语法。LCH 通道是亮度、色度和色相。色调是一种角度,就像在 HSL 和 HWB 中一样。亮度是一个介于 0 到 100 之间的值,但与 HSL 的亮度不同,它是一种以人为中心的特殊“感知线性”亮度。色度与饱和度类似,范围是 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 是 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 白点。
优点
- 线性光访问具有方便的用例。
- 非常适合混合物理色。
缺点
- 不像 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);
}
看不到 Codepen 演示?
如果从一个空间中的一种颜色转换为一个完全不同的空间中的颜色,会发生什么情况:
.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%));
}
看不到 Codepen 演示?
幸运的是,
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 个颜色停止点之间的色调,并查看色调插值选择的效果以及颜色空间如何改变渐变结果。效果可以截然不同;就颜色工具条而言,四个新技巧就这么简单。
不同颜色空间中的渐变
每种颜色空间都具有独特的形状和颜色排列方式,因此会产生不同的渐变。请查看以下示例,尤其是“蓝到白”区域。 我们来看看每种颜色空间的处理方式请注意,中间有多少个颜色变为紫色,在插值期间称为“色调偏移”。
看不到 Codepen 演示?
显示的图片只是 Codepen 中众多示例中的一个。您可以试用 Canary 版或 Safari 技术预览版,亲自体验一下这些功能。
这些空间中的一些渐变效果会比其他渐变更鲜艳,或者通过
死区的渐变效果会更少。与为了便于用户编写颜色而优化的空间(例如
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%));
}
看不到 Codepen 演示?
此示例在 hwb 中使用相同的颜色,但指定了插值到 hwb 或 oklab 的颜色空间。
hwb
非常适合用于高强度但可能存在死区或亮点(请参阅顶部示例中的青色热点)的色彩空间。Oklab 非常适合用于保持饱和的感知线性渐变。此功能非常有趣,因为您可以尝试几种不同的颜色空间,看看您最喜欢哪种渐变。
下面是一个 Codepen,他们正在尝试使用渐变和颜色空间、混合和匹配策略探索各种可能性。即使是从黑色到白色,每种颜色空间的过渡也有所不同!
看不到 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)
迁移到高清 CSS 颜色
更新 Web 项目颜色以支持广色域显示屏的方法主要有两种:
-
优雅降级
使用新的颜色空间,让浏览器和操作系统根据显示功能确定要显示的颜色。 -
渐进式增强功能
使用@supports
和@media
评估用户浏览器的功能,如果满足条件,则提供广色域色彩。
如果浏览器无法识别
display-p3
颜色:
color: red;
color: color(display-p3 1 0 0);
如果浏览器理解
display-p3
颜色:
color: red;
color: color(display-p3 1 0 0);
每种方式各有优缺点。下面简要列出了其优缺点:
优雅降级
- 优点
- 最简单的路线。
- 如果不是广色域显示屏,浏览器会对映射或限制到 sRGB 进行色域处理,因此应由浏览器负责。
- 缺点
- 浏览器可能会针对您不喜欢的颜色实施色域限制或色域映射。
- 浏览器可能无法识别颜色请求,并完全失败。但是,可以通过指定两次颜色来缓解这种情况,让级联回退到它可以识别的上一个颜色。
渐进式增强功能
- 优点
- 通过受管理的色彩保真度实现更多控制。
- 不影响当前颜色的附加策略。
- 缺点
- 您需要管理两种不同的颜色语法。
- 您需要管理两种不同的色域。
检查色域和颜色空间支持
该浏览器允许检查是否支持 CSS 和 JavaScript 的广色域功能和颜色语法。无法获得用户的确切色域,而是提供了一个通用的答案,以便维护用户隐私。不过,可以提供确切的颜色空间支持,因为它并非特定于用户硬件的功能,例如色域。
色域支持查询
以下代码示例检查访问用户在其显示屏中显示的颜色范围。
正在通过 CSS 检查
最具体的支持查询是
dynamic-range
媒体查询:
@media (dynamic-range: high) {
/* safe to use HD colors */
}
可以使用
color-gamut
媒体查询咨询大致支持或更多支持:
@media (color-gamut: srgb) {
/* safe to use srgb colors */
}
@media (color-gamut: p3) {
/* safe to use p3 colors */
}
@media (color-gamut: rec2020) {
/* safe to use rec2020 colors */
}
此外,还有两个媒体查询可用于检查支持情况:
从 JavaScript 检查
对于 JavaScript,可以调用
window.matchMedia()
函数并向其传递媒体查询以进行评估。
const hasHighDynamicRange = window
.matchMedia('(dynamic-range: high)')
.matches;
console.log(hasHighDynamicRange); // true || false
const hasP3Color = window
.matchMedia('(color-gamut: p3)')
.matches;
console.log(hasP3Color); // true || false
您可为其余媒体查询复制上述模式。
颜色空间支持查询
以下代码示例检查了访问用户的浏览器以及它选择使用的颜色空间。
正在通过 CSS 检查
可以使用
@supports
查询来查询各个颜色空间支持情况:
@supports (background: rgb(0 0 0)) {
/* rgb color space supported */
}
@supports (background: color(display-p3 0 0 0)) {
/* display-p3 color space supported */
}
@supports (background: oklch(0 0 0)) {
/* oklch color space supported */
}
从 JavaScript 检查
对于 JavaScript,可以调用
CSS.supports()
函数并传递属性和值对,以查看浏览器是否可以理解。
CSS.supports('background: rgb(0 0 0)')
CSS.supports('background: color(display-p3 0 0 0)')
CSS.supports('background: oklch(0 0 0)')
整合硬件检查和解析检查
在等待每个浏览器实现这些新的颜色功能时,最好同时检查硬件功能和颜色解析功能。我经常用以下来将颜色逐渐增强为高清:
:root {
--neon-red: rgb(100% 0 0);
--neon-blue: rgb(0 0 100%);
}
/* is the display HD? */
@media (dynamic-range: high) {
/* does this browser understand display-p3? */
@supports (color: color(display-p3 0 0 0)) {
/* safe to use display-p3 colors */
--neon-red: color(display-p3 1 0 0);
--neon-blue: color(display-p3 0 0 1);
}
}
使用 Chrome 开发者工具调试颜色
Chrome 开发者工具已更新,并配备了新工具,以帮助开发者创建、转换和调试高清颜色。
已更新颜色选择器
颜色选择器现在支持所有新的颜色空间。允许作者像与往常一样与频道值互动。
色域边界
此外,还添加了色域边界线,在 srgb 和 display-p3 色域之间绘制一条线。明确表示所选颜色属于哪种色域。
这有助于作者直观地区分高清和非高清颜色。与
color()
函数和新的颜色空间一起使用时,这种颜色尤为有用,因为它们能够生成非高清和高清颜色。如果您想查看所选颜色的色域,请弹出颜色选择器,直接查看!
转换颜色
多年来,开发者工具一直在支持的格式(例如 hsl、hwb、rgb 和十六进制)之间转换颜色。在“Styles”窗格中对方形色样添加
shift + click
,以执行此转换。新的颜色工具不仅会循环显示转化,还会生成一个弹出式窗口,供作者查看并选择所需的转化。
在转换时,请务必了解是否为了适应空间而截断转换。现在,开发者工具有一个警告图标,表示转换后的颜色会提醒您注意这一裁剪。
请参阅他们 近期发布的公告,详细了解开发者工具中的更多 CSS 调试功能。
总结
网络上的非 sRGB 颜色空间尚处于早期阶段,但我相信,随着时间的推移,设计师和开发者会越来越多地使用它们。例如,了解要在哪种颜色空间上构建设计系统是成为创作者工具条的绝佳工具。每种颜色空间都有独特的功能,以及将其被添加到 CSS 规范的原因,可以从小着手,然后根据需要添加。
尽情玩这些新的彩色玩具吧!更加生动、一致的操作和插值,从整体上为用户提供更加丰富多彩的体验。
附加阅读材料
- https://lea.verou.me/2020/04/lch-colors-in-css-what-why-and-how/
- https://www.w3.org/Graphics/Color/Workshop/slides/lilley/lilley.html
- https://darker.ink/writings/Towards-richer-colors-on-the-Web
- https://bottosson.github.io/posts/colorpicker/
- https://www.w3.org/Graphics/Color/Workshop/slides/Erias.pdf
- https://atmos.style/blog/lch-color-space
- https://stripe.com/blog/accessible-color-systems
- https://cran.r-project.org/web/packages/colordistance/vignettes/color-spaces.html
- https://afc163.github.io/color3d/
- https://github.com/nschloe/colorio#gamut-visualization
- https://www.learnui.design/tools/gradient-generator.html
- https://webkit.org/blog/10042/wide-gamut-color-in-css-with-display-p3/
- https://www.w3.org/TR/css-color-4/
- https://www.w3.org/TR/css-color-5/
- https://en.wikipedia.org/wiki/CIE_1931_color_space
- https://www.joshwcomeau.com/css/color-formats/
- https://ciechanow.ski/color-spaces/