网络上不断扩展的颜色范围

Avatar of Ollie Williams
Ollie Williams

DigitalOcean 为您的旅程的每个阶段提供云产品。立即开始使用 $200 免费额度!

CSS 早在 1996 年就引入到了网络。当时,大多数计算机显示器都很糟糕。CSS 的颜色——无论使用 RGB、HSL 还是十六进制格式定义——都适应了当时的显示器,都在 sRGB 色彩空间内。

大多数新设备都有一个 _广色域_ 显示屏。一个 **色域** 是可以显示的颜色范围。**广色域** 显示屏能够显示比 sRGB 更多的颜色。它们使用 Display P3 色彩空间。(还有 Rec.2020,一个更大的色彩空间,但这非常罕见,目前还不太值得考虑。) 正如 CSS 工作组的 Lea Verou 所说,“我们的网站看起来很暗淡,因为屏幕的进步速度比 CSS 颜色快。”如果我们想充分利用大多数屏幕能够显示的颜色范围,我们需要使用新的 CSS 颜色格式:lablchdisplay-p3

可以在 Panic 网站(曾经流行的 Coda 文本编辑器和仍然非常流行的 Untitled Goose Game 的创建者)或名为 Playdate 的产品的营销网站上找到真实示例。它们都利用了引人注目的鲜艳和强烈的颜色,通过使用 display-p3 来实现独特生动。

Screenshot taken from the Panic website showing bright pink text against a stark black background.
Panic 的网站 以一种引人注目的粉红色为特色。

为了了解 sRGB 中缺失的颜色范围,请查看以下 Pen。内部框包含一个超出 sRGB 色域的颜色。外部框显示该颜色被限制在 sRGB 色域(意味着浏览器能够显示的最接近的等效颜色,不使用 display-p3lablch)。(请注意,目前支持仅限于 Safari 用户。)

Safari Technology Preview 中的颜色选择器很有帮助地显示了哪些颜色超出了 sRGB 色域。

Screenshot of a color picker going from bright green to black with a light curved line signifying the point where colors go past the typical sRGB range.
任何在白色线条之上或之右的颜色都超出 sRGB 色域

新语法的概述

在深入研究 lab()lch()color() 函数的语法之前,让我们看一下新的 rgb()hsl() 语法(所有网络浏览器都支持,除了 Internet Explorer)。

类型旧语法新语法
RGBrgb(0, 128, 255)rgb(0 128 255)
RGBargba(0, 128, 255, 0.5)rgb(0 128 255 50%)
HSLhsl(198, 28%, 50%)hsl(198 28% 50%)
HSLahsla(198, 28%, 0.5)hsl(198deg 28% 50% / 50%)
来源:@mathias 

在旧语法中,每个数字都是用逗号分隔的:rgb(200, 100, 20);逗号不再是必需的,因此空格分隔的值 rgb(200 100 20); 是有效的。要指定透明度,现在可以使用 rgb(200 100 20 / 50%),而不是使用 rgba()hsla()。新语法并没有真正的优势,但值得一看,因为它们与 lch()lab()color() 的语法匹配。

类型语法
Lablab(56.29% -10.93 16.58 / 50%)
color()color(sRGB 0 0.5 1 / 50%)
LCHlch(56.29% 19.86 236.62 / 50%

lab()lch()color() 始终使用空格分隔的数字(不允许逗号),并使用斜杠后跟百分比来指定透明度。让我们看看它们是如何工作的。

CSS color() 函数和 display-p3 色彩空间

color() 函数允许在特定色彩空间中指定颜色(而不是使用 rgb()hsl() 或十六进制使用的 sRGB 色彩空间)。为了使用广色域颜色,我们需要指定的色彩空间是 display-p3,它使用三个数值,代表 color: 1 0 0 是纯红色、0 0 1 是纯蓝色,0 1 0 是纯绿色的红、绿、蓝通道。

background-color: color(display-p3 1 0 0.331); /* vibrant pink color */

在撰写本文时,display-p3 是访问高色域颜色的唯一方法,自 2017 年以来在 Safari 中一直得到支持。但是,一旦实现,lab()lch() 将是更好的选择(Chrome 和 Safari 目前正在开发中)。以下是来自 Lea Verou 的看法: 

display-p3 不是感知均匀的,并且难以通过调整其参数来创建变体(更亮或更暗,更生动或更不生动等)。此外,它是一个短期解决方案。它现在有效,因为比 P3 色域更广的屏幕很少见。一旦硬件再次进步,color(display-p3 ...) 将会遇到与 sRGB 颜色今天遇到的相同问题。LCH 和 Lab 与设备无关,并且可以表示人类视觉的整个色域,因此无论硬件如何发展,它们都将有效。

更好的亮度:Lab 和 LCH

您可能在网上看到过 文章 争论说 HSL 比 RGB 或十六进制值更容易理解。

以下是 Chris Coyier 在 2015 年的观点

HSLa 的真正吸引力在于它更直观地理解更改值会对颜色产生什么影响。增加第二个值将增加该颜色的饱和度。减少第三个值将降低该颜色的亮度。这使得在动态情况下创建自己的颜色变体变得更加容易。

虽然 HSL 可能比十六进制或 RGB 更容易理解,但它远非完美。它计算亮度的方式根本不符合人类的感知。根据 HSL,hsl(240deg 100% 50%)hsl(60deg 100% 50%) 具有相同的亮度,50%。让我们比较一下这两个。

在人眼中,蓝色看起来更暗。正如 Brian Kardell 所说: 

只有在包含我们眼睛实际工作方式的感知,而不是机器喜欢存储和显示的方式的情况下,才能很好地完成混合颜色、变亮、变暗等操作。

这里是一个视觉示例 来自 Lea Verou,它展示了 Lab/LCH 比 HSL 的优势。 她评论道: 

一个在不同亮度下创建相同颜色美观渐变的技巧是转换为 Lab,改变 L,然后转换回 HSL/RGB。

“具有相同饱和度和亮度的光谱中所有色调的感知亮度。[…] 很明显它们是不同的。”——Brian Kardell(图片:Rob Waychert

Lab 和 LCH 都使用 CIELAB 色彩空间,该色彩空间旨在与人类视觉相一致。如果您赋予两种颜色相同的亮度值,它们在人眼中看起来具有相同的亮度,无论它们的色调如何。

Lab

background-color: lab(40% 83 -104); /* a shade of purple */

lab() 中的 L 代表亮度,并以百分比表示(对于超亮的白色可以高达 400%,但通常在 0% 到 100% 之间)。A 和 B 不代表任何东西——它们是颜色通道。A 是绿色(负值)和红色(正值)之间的数值,而 B 是蓝色(负值)和黄色(正值)之间的数值。亮度对我们来说很容易理解。然而,红/绿值和蓝/黄值并不直观。LCH 可能是一个更好的选择。

LCH

background-color: lch(69% 56 244); /* a shade of blue */

lch() 是新颜色值中最易于人类理解的。L 仍然代表亮度(并且以完全相同的方式工作),C 代表色度,H 代表色调。色度在很大程度上类似于饱和度,但也可以被认为是颜色强度或鲜艳度。与其他新颜色格式不同,您可以实际预测更改这些单个值将产生的影响——在这一点上它类似于 HSL。最直观的理解方法是尝试使用这个 LCH 颜色选择器

定义回退

我们需要考虑两种支持:浏览器对新 CSS 颜色值的支持以及屏幕显示这些颜色的能力。

对于不支持颜色函数的浏览器,回退到最接近的匹配 sRGB 值很容易,就像我们过去定义回退属性一样。

.pink-text {
  color: rgb(255, 0, 79); /* Will be used as a fallback */
  color: color(display-p3 1 0 0.331); /* Will be used if supported */
}

由于级联的存在,如果浏览器不理解上面的示例中的第二行代码,它将被忽略,并且将使用 rgb() 值。每次要指定颜色时都写两行 CSS 会很麻烦。CSS 变量是解决此问题的绝佳方法。在本例中,我们将使用 @supports 来判断浏览器是否支持 CSS 中的颜色函数。

/* https://webkit.org/blog/10042/wide-gamut-color-in-css-with-display-p3/ */
:root {
  --bright-green: rgb(0, 255, 0);
}


/* Display-P3 color, when supported. */
@supports (color: color(display-p3 1 1 1)) {
  :root {
    --bright-green: color(display-p3 0 1 0);
  }
}


header {
  color: var(--bright-green);
}

如果颜色对您的设计尤为重要,您可以使用背景图像,因为大多数浏览器都支持图像中的高色域颜色。

@supports not (color: color(display-p3 1 0 0.331)) {
  @supports (-webkit-background-clip: text){
    .pink-text {
      background-image: url("pink-P3.png");
      background-size: cover;
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
    }
  }
}


.pink-text {
  color: rgb(255, 0, 79);
  color: color(display-p3 1 0 0.331);
}

有一个 PostCSS 插件可以将 lab() 和 lch() 函数转换为 rgb()。如果您使用 Sass,Miriam Suzanne 开发了一个名为 Blend 的工具。

用于颜色的媒体查询

@supports 告诉我们浏览器是否支持相关的 CSS 语法。它不能告诉我们用户的显示器是否能够真正显示某些颜色值。如果显示器不支持高色域颜色,屏幕将显示最接近的等效 sRGB 颜色。这意味着所有显示器都将得到照顾,无需编写任何额外代码。

但是,如果您想手动选择回退颜色,而不是让浏览器为您计算,您可以传递第二个颜色值到 color() 函数。然而,这将需要浏览器支持颜色函数(但对第二个参数的支持尚未在任何浏览器中实现)。

background-color: color(display-p3 1 0 0.331, #f54281);

如果您需要更多控制来执行一些复杂的操作,媒体查询 4 级规范提供了一个新的 color-gamut 媒体查询 来帮助我们。

@media (color-gamut: p3) { 
  /* Code to run only on hardware that supports P3 color */
}

在这个例子中,我们显然是在检查对 P3 的支持,但我们也可以检查之前提到的 rec-2020 色彩空间,它的色域比 P3 更广。目前支持 rec-2020 的屏幕数量很少,只包括高清电视,这意味着在不久的将来,它们不会成为开发人员的常见目标。您也可以检查对 sRGB 的支持,但现在几乎所有显示器都支持 sRGB。另一方面,color-gamut 查询在撰写本文时具有 相当不错的浏览器支持

旁注:动态范围媒体查询

Safari 13.1 发行说明 中,动态范围媒体查询用于有条件地应用 P3 颜色。显然,这不是一个好的用例。根据 Florian Rivoal媒体查询规范 的编辑)的说法,该查询旨在用于视频。

[S]ome screen can show ultra-bright lights for brief amounts of times, that are used in videos for things like sparks, direct sunlight, etc. This is much brighter than white, and isn’t meant to be used with static images. It would be uncomfortable, and would also damage the screen.

另一个旁注:设计工具支持

不幸的是,流行的网页设计工具,如 Figma、Sketch 和 XD 目前不支持 Lab、LCH 或 P3 色彩空间。但是,Photoshop 确实有一个 Lab 颜色选择器。


好了!CSS 颜色正在扩展,与此同时,屏幕支持的色域也比以往任何时候都多。对于那些喜欢颜色的朋友来说,这是一个令人兴奋的时代!