CSS 颜色模块 第5级

W3C 工作草案

更多关于该文档的信息
此版本:
https://www.w3.org/TR/2025/WD-css-color-5-20250318/
最新发布版本:
https://www.w3.org/TR/css-color-5/
编辑草案:
https://drafts.csswg.org/css-color-5/
先前版本:
历史:
https://www.w3.org/standards/history/css-color-5/
反馈:
CSSWG 问题库
编辑:
Chris Lilley (W3C)
Una Kravets (Google)
Lea Verou (特邀专家)
Adam Argyle (Google)
为此规范建议编辑:
GitHub 编辑器
差异规范:
测试套件:
https://wpt.fyi/results/css/css-color/

摘要

此模块扩展了 CSS 颜色[css-color-4],以添加颜色修改函数、自定义颜色空间 (ICC 配置文件)、contrast-color()、light-dark() 和 device-cmyk()。

CSS 是一种用于描述结构化文档(例如 HTML 和 XML)在屏幕、纸张等媒介上渲染的语言。

本文档状态

本节描述了本文档在发布时的状态。当前W3C出版物列表及本技术报告的最新修订版可在W3C技术报告索引https://www.w3.org/TR/中找到。

本文档由 CSS 工作组作为工作草案发布,采用推荐标准流程。 作为工作草案发布并不意味着 W3C 及其成员的认可。

这是一份草案文件,可能随时被其他文件更新、替换或废弃。 引用本文档作为正在进行的工作以外的任何内容都是不合适的。

请通过在 GitHub 中提交问题(首选)发送反馈, 并在标题中包含规范代码“css-color”,如下所示: “[css-color] …评论摘要…”。 所有问题和评论都已存档。 或者,反馈可以发送到(已存档)公共邮件列表 www-style@w3.org

本文档受 2023年11月3日 W3C 流程文档的约束。

本文档由一个在 W3C 专利政策下运作的小组制作。 W3C 维护一份与该小组交付成果相关的任何专利披露的公开列表; 该页面还包括披露专利的说明。 任何实际知晓某项专利,并认为该专利包含必要权利要求的个人, 必须根据 W3C 专利政策第 6 节披露该信息。

1. 简介

本节内容不具有规范性。

此模块添加了新函数 contrast-color()color-mix()light-dark(), 并使用相对颜色语法扩展了现有函数。

它还扩展了 color() 函数, 以便不仅可以使用预定义的颜色空间, 还可以使用由 ICC 配置文件定义的自定义颜色空间 (包括校准的 CMYK) 在 CSS 中。

它还添加了 device-cmyk, 一种未校准 cmyk 颜色的表示形式。

2. <color> 语法

CSS中的颜色由 <color> 类型表示:

<color> = <color-base> | currentColor | <system-color> | 
      <contrast-color()> | <device-cmyk()>  | <light-dark()>

<color-base> = <hex-color> | <color-function> | <named-color> | <color-mix()> | transparent
<color-function> = <rgb()> | <rgba()> |
              <hsl()> | <hsla()> | <hwb()> |
              <lab()> | <lch()> | <oklab()> | <oklch()> |
              <color()>

绝对颜色 是一个 <color> 其计算值具有绝对的色度解释。 这意味着该值不包括:

这些值也不能在 <color-mix()> 或相对颜色语法中使用。

3. 混合颜色:color-mix() 函数

Web 开发人员、设计工具和设计系统开发人员经常使用颜色函数来辅助扩展其组件颜色关系的设计。 随着支持多平台和多种用户偏好(例如 UI 中深色模式功能的增强)的设计系统的使用日益增多, 这种无需手动设置颜色,而是通过单一来源计算配色方案的方式变得更加有用。

LCH 颜色选择器
美国等值区域图

上图为一个在 CIE LCH 空间中操作的颜色选择器。 此处,一对颜色被用于在色度-亮度平面(色相恒定)上定义一个色阶。 下图为在等值区域图上使用的该色阶。

目前,Sass、HSL 值上的 calc() 或 PostCSS 被用于实现此目的。 然而,预处理器无法处理动态调整的颜色; 所有当前的解决方案都局限于 sRGB 色域以及 HSL 的感知局限性 (颜色在色轮中聚集在一起, 并且两种视觉上亮度不同的颜色, 例如黄色和蓝色,可能具有相同的 HSL 亮度)。

为了满足这一需求,color-mix() 函数接受两个 <color> 规范, 并返回在给定的 <color-space> 中, 按指定量混合它们的结果。

color-mix() = color-mix( <color-interpolation-method> , [ <color> && <percentage [0,100]>? ]#{2})
测试

3.1. 百分比归一化

百分比必须在 0% 到 100% 之间。特别禁止负百分比。百分比按如下方式归一化:

  1. p1 为第一个百分比,p2 为第二个。

  2. 如果两个百分比都被省略,它们都默认为 50% (两个颜色的等量混合)。

  3. 否则,如果 p2 被省略,则其值为 100% - p1

  4. 否则,如果 p1 被省略,则其值为 100% - p2

  5. 否则,如果两者相加大于 100%,它们会相应地缩放,使它们的和等于 100%。

  6. 否则,如果两者相加小于 100%,则将总和保存为 alpha 乘数。 然后它们会相应地缩放,使它们的和等于 100%。

这意味着 p1 变为 p1 / (p1 + p2) 并且 p2 变为 p2 / (p1 + p2)。

测试
这些语法形式都是等效的:
color-mix(in lch, purple 50%, plum 50%)
color-mix(in lch, purple 50%, plum)
color-mix(in lch, purple, plum 50%)
color-mix(in lch, purple, plum)
color-mix(in lch, plum, purple)
color-mix(in lch, purple 80%, plum 80%)

所有这些都会生成 purple 和 plum 的 50-50 混合, 在 lch 中: lch(51.51% 52.21 325.8) 即 rgb(68.51% 36.01% 68.29%)。

然而,这种形式 不是 一样的,因为 alpha 小于 1:

color-mix(in lch, purple 30%, plum 30%)

这会生成 lch(51.51% 52.21 325.8 / 0.6) 即 rgb(68.51% 36.01% 68.29% / 0.6)。

3.2. 计算 color-mix 的结果

在归一化两个百分比后,结果通过以下算法产生:

  1. CSS Color 4 第 12 节. 颜色插值 所述, 两个颜色转换为指定的插值 <color-space>, 考虑到任何 相似组件

  2. 然后,颜色在指定的颜色空间中进行插值, 如 CSS 颜色 4 § 12. 颜色插值中所述。 如果指定的颜色空间是 cylindrical-polar-color 空间, 则 <hue-interpolation-method> 控制色相的插值,如 CSS 颜色 4 § 12.4 色相插值中所述。 如果未指定 <hue-interpolation-method>, 则如同指定了 shorter 一样。

  3. 如果在百分比归一化过程中产生了 alpha 乘数, 则插值结果的 alpha 分量将乘以 alpha 乘数。

测试

混合的结果是在从第二个颜色到第一个颜色的渐进线上指定百分比处的颜色。

注意:因此,0% 的百分比仅返回转换为指定颜色空间的另一个颜色, 而 100% 返回转换为指定颜色空间的相同颜色。

此示例生成 40% peru 和 60% palegoldenrod 的混合。
color-mix(in lch, peru 40%, palegoldenrod)

混合是在 lch 颜色空间中进行的。 这是一个俯视图,沿着中性 L 轴观察:

两个颜色的混合及混合输出。 我们沿着 CIE L 轴观察 ab 平面。 有两个轴,标记为 ab,它们在原点交叉, 该原点位于图的中心。

peru 和 palegoldenrod 在 CIE LCH 中的混合。 Peru 的色相角从正 a 轴测量,为 63.677 度, 而 palegoldenrod 的色相角为 98.834 度。 Peru 的色度或离中心中性轴的距离为 54.011, 而 palegoldenrod 的色度为 31.406。 所有可能的混合都位于曲线沿线。显示了 40%/60% 的混合。

计算如下:

此示例在 lch 颜色空间中生成青色和橄榄色的混合色, 其中每个 lch 分量为青色值的 65% 和橄榄色值的 35%。

注意:对色相和色度进行插值 使中间颜色的饱和度 与终点颜色一样饱和。

color-mix(in lch, teal 65%, olive);

两个颜色的混合及混合输出。 我们沿着 CIE L 轴观察 ab 平面。 有两个轴,标记为 ab,它们在原点交叉, 该原点位于图的中心。

teal 和 olive 的混合。 Teal 的色相角从正 a 轴测量,为 196.4524 度, 而 olive 的色相角为 99.5746 度。 Teal 的色度或离中心中性轴的距离为 31.6903, 而 olive 的色度为 56.8124。 混合位于虚线曲线沿线。显示了 65%/35% 的混合。

计算如下:

3.3. 混合颜色空间对 color-mix 的影响

选择的混合颜色空间会对最终结果产生很大影响。

该示例是白色和黑色的 50% 混合, 在三个不同的颜色空间中。
color-mix(in lch, white, black);
color-mix(in xyz, white, black);
color-mix(in srgb, white, black);

计算如下:

LCH 中的混合给出 L 值为 50%, 一个完美的中灰,完全符合预期 (在 Lab 中混合也会产生相同的结果, 因为 LCH 和 Lab 的亮度轴是相同的)。

XYZ 中的混合结果过亮; XYZ 是线性光,但不是感知一致的。 sRGB 中的混合结果也稍微过亮; sRGB 既不是感知一致的,也不是线性光。

该示例生成 红色和天蓝色的混合, 在 xyz 颜色空间中, 混合结果为 75.23% 红色的值 (因此,24.77% 是天蓝色的值)。
color-mix(in xyz, rgb(82.02% 30.21% 35.02%) 75.23%, rgb(5.64% 55.94% 85.31%));

计算如下:

该示例是白色和蓝色的 50% 混合, 在三个不同的颜色空间中。

color-mix(in lch, white, blue);
color-mix(in oklch, white, blue);
color-mix(in srgb, white, blue);

计算如下:

该示例是两个颜色的混合, 在 hsl 颜色空间中, 其中一个颜色 超出了 sRGB 色域。
color-mix(in hsl, color(display-p3 0 1 0) 80%, yellow);

计算如下:

3.4. 非完全不透明的 alpha 对 color-mix 的影响

到目前为止,所有 color-mix() 示例 都使用了完全不透明的颜色。 为了简化示例, 省略了预乘和反预乘步骤, 因为这些步骤只会乘以 1 和除以 1, 所以结果不会改变。

在一般情况下, 颜色可能具有非单位 alpha 分量, 因此预乘、插值、反预乘步骤 不得省略。

此示例是 25% 的半透明红色 和 75% 的半透明绿色, 在 sRGB 中混合。 显示了正确(预乘) 和不正确(非预乘) 的计算过程。
color-mix(in srgb, rgb(100% 0% 0% / 0.7) 25%, rgb(0% 100% 0% / 0.2));

计算如下:

错误的计算如下:

这是一个巨大的差异;正确和错误结果之间的 ΔE2000 为 30.7!

当百分比归一化生成 alpha 乘数时,计算与之前相同,只是多了最后一步。

此示例与前一个类似, 25% 半透明红色和 75% 半透明绿色, 在 sRGB 中混合。

但在此示例中,百分比指定为 第一个颜色的 20% 和第二个颜色的 60%。 这加起来为 80%,因此 alpha 乘数为 0.8。

混合百分比然后被缩放 乘以 100/80:
20% * 100/80 = 25%
60% * 100/80 = 75%
最终得到与前一个示例相同的混合百分比。

color-mix(in srgb, rgb(100% 0% 0% / 0.7) 20%, rgb(0% 100% 0% / 0.2) 60%);

计算如下:

注意: 不要将插值后的 alpha 乘以 alpha 乘数然后再用于解乘。 如果混合百分比未缩放为 100%,这样做是正确的, 但实际上它们已缩放,因此这样做会使混合颜色调整两次。

4. 相对颜色

4.1. 相对颜色的处理模型

在本规范的先前级别中, 颜色函数只能以绝对方式指定颜色, 即直接指定所有颜色分量。

新的相对颜色语法 扩展了现代颜色语法,允许使用颜色函数修改现有颜色: 如果指定了原始颜色, 那么每个颜色分量 (以及 alpha 分量,如果指定) 可以要么直接指定, 要么从原始颜色中获取 (并可能使用数学函数进行修改)。

原始颜色和相对颜色不必使用相同的颜色函数。

所有操作都在相对颜色函数的颜色空间中进行;如果原始颜色原始指定颜色空间使用了不同的颜色函数, 它会首先转换为所选的颜色函数, 以便它具有对分量有意义的值,并且分量关键字指的是相对颜色的颜色空间,而不是原始颜色的颜色空间。

如果省略相对颜色的 alpha 值, 它将默认为原始颜色的 alpha 值(而不是像在绝对语法中那样默认为 100%)。

当使用相对颜色语法时,颜色分量值, 无论是直接指定的还是由颜色空间转换产生的, 都不会被限制在参考范围内,而是按原样保留。 如果目标颜色空间能够表示它们,这将保留超出色域的值。

然而,当使用相对颜色语法时,alpha 分量值, 无论是直接指定的还是由颜色空间转换产生的,被限制在参考范围内。

缺失分量的处理方式与CSS 颜色 4 § 12.2 缺失分量的插值相同: 检查原始颜色空间和相对函数颜色空间是否存在相似分量,然后将其作为缺失分量沿用

虽然相对颜色语法的大多数用法 会在其相应的参数中使用分量关键字, 但您可以在任何位置使用它们。

在正常位置之外使用分量时要小心; 当百分比解析为数字时, 如果这些数字用在不同的地方, 则没有“神奇的缩放”来解释位置的改变。

4.2. 相对颜色语法

下面列出了每个函数为适应相对颜色而进行的语法更改的精确细节, 但它们都遵循一个共同的结构:

分量关键字返回一个<number>,或 none; 如果它们最初被指定为<percentage><angle>, 则该<percentage> 将解析为<number>,并且该<angle> 将解析为范围 [0, 360] 内的度数<number>(这是规范单位)。

测试
例如,如果颜色是用 <percentage>指定的, 则在相同颜色空间中的 RCS 将使用解析后的 <number>形式:
html { --bluegreen:  oklab(54.3% -22.5% -5%); }
.overlay {
  background:  oklab(from var(--bluegreen) calc(1.0 - l) calc(a * 0.8) b);
}

在这个示例中,指定的百分比被解析为数值, 生成 oklab(0.543 -0.09 -0.02)。 结果颜色是 l = 1 - 0.543 = 0.457, a = -0.09 * 0.8 = -0.072, b 不变为 -0.02: oklab(0.457 -0.072 -0.02)。

例如,如果原始颜色的色调 <angle>以度数指定, 则相同颜色空间中的 RCS 将使用解析后的 <number>形式:
html { --base:  oklch(52.6% 0.115 44.6deg) }
.summary {
  background:  oklch(from var(--base) l c  calc(h + 90));
}

在这个示例中,结果颜色是 oklch(0.526 0.115 134.6)。

如果原始颜色的色调<angle>以其他单位指定, 如弧度或转数, 解析后得到的仍然是度数形式 <number>

通过在数学函数中使用组件关键字, 可以更高级地操作原始颜色
html { --color: green; }
.foo {
    --darker-accent: lch(from var(--color) calc(l / 2) c h);
}

在此示例中,通过将其亮度减半来使原始颜色变暗, 而不改变颜色的任何其他方面。

另请注意,原始颜色是一个颜色关键字 (因此是 sRGB), 但由于在 lch() 函数中使用,它会自动解释为 LCH 颜色。

例如,如果主题颜色指定为不透明, 但在特定情况下您需要它部分透明:
html { --bg-color:  blue; }
.overlay {
    background:  rgb(from var(--bg-color) r g b / 80%);
}

在此示例中,原始颜色的 r、g 和 b 分量保持不变, 通过使用从原始颜色中获取其值的关键字来指定它们, 但将不透明度设置为 80% 以使其略微透明, 而不管原始颜色的不透明度如何。

例如,一个超出 sRGB 色域的 Display P3 颜色 仍然可以表示, 因为它没有被裁剪。
--vivid-yellow:  color(display-p3 1 1 0);
--paler-yellow:  color(from var(--vivid-yellow) srgb r g calc(b + 0.5));

此处 --vivid-yellow 转换为 sRGB 后, 是 rgb(100% 100% -34.63%) 并且负蓝色分量未被裁剪。 RCS 计算的结果是 rgb(100% 100% 15.37%)

例如,尝试将原始颜色中 0.7 的 alpha 值加倍 会导致结果中的 alpha 值为 1,而不是 1.4。
--tan:  oklch(78% 0.06 75 / 0.7);
--deeper-tan:  oklch(from var(--tan) l c h / calc(alpha * 2));
例如,对颜色进行粗略的灰度处理:
--blue-into-gray: rgb(from var(--color)
                    calc(r * .3 + g * .59 + b * .11)
                    calc(r * .3 + g * .59 + b * .11)
                    calc(r * .3 + g * .59 + b * .11));

使用此方法,红色 将变为 rgb(76.5 76.5 76.5)石灰色 将变为 rgb(150.45 150.45 150.45), 而蓝色将变为 rgb(150.45 150.45 150.45)。 像深橄榄绿色这样更温和的颜色, 其 RGB 值为 rgb(85 107 47), 将变为 rgb(93.8 93.8 93.8)

(粗略是因为首先, 虽然这看起来像亮度计算, 但红、绿和蓝值是在伽马编码空间中操作的, 而不是线性光空间; 其次, 权重因子是用于已过时的 NTSC 颜色空间的, 而不是 sRGB。)

(另请注意,这只是为了说明语法; 一种更简单、更准确的灰度处理颜色的方法是使用 oklch() 函数, 因为该颜色空间对人类感知更准确:oklch(from var(--color) l 0 h) 保留亮度, 但将色度(决定颜色“鲜艳”程度的因素)归零。)

例如,

color: color(from color(srgb 0 0 0 / 60%) srgb alpha 0.6 0.6 / 0.9);

alpha 分量解析为<number>, 得到 0.6;因此结果颜色为 color(srgb 0.6 0.6 0.6 / 0.9)

然而,在第二个示例中,alpha 再次解析为 0.6, 由于 rgb() 语法中颜色分量范围为 0 到 255,因此会产生截然不同的颜色:

color: rgb(from rgb(0 0 0 / 60%) alpha 153 153 / 0.9);

结果为 rgb(0.6 153 153 / 0.9)不是 rgb(153 153 153 / 0.9)

在此示例中,消色差原始颜色缺少色相; 相对颜色也缺少色相, 这会影响使用该颜色的渐变。
html { --bg:  hsl(none 3% 50%); }
.foo {
    --darker-bg:  oklch(from var(--bg) calc(l * 0.8) c h);
}
.bar {
    background: linear-gradient(in Oklab to right,   var(--darker-bg),   #4C3);
}

--bg 转换为 OKLCh 后的值为 oklch(0.592 0.009 17.42) 但相似的色相分量被沿用 得到 oklch(0.592 0.009 none)。 然后这些值在相对函数中使用,得到 较暗的颜色 oklch(0.474 0.009 none)。

渐变中的浅绿色是 oklch(0.743 0.222 141.6), 因此,在插值时,另一种颜色采用该色相, 变为 oklch(0.474 0.009 141.6)。

因此,渐变将具有恒定的绿色色调。

如果实现未能执行此沿用操作, 灰色的 --darker-bg 将具有 0 的色相, 从而在渐变开始时产生不希望的微红色调。

正确的(上方)和不正确的(下方,微红色)渐变。
正确的(上方)和不正确的(下方,微红色)渐变。

但是,如果对缺失值进行计算,none 将被视为 0。

4.3. 相对 sRGB 颜色

现代颜色语法rgb()rgba() 函数的语法扩展如下:

<modern-rgb-syntax> = rgb( [ from <color> ]?
        [ <number> | <percentage> | none]{3}
        [ / [<alpha-value> | none] ]?  )
<modern-rgba-syntax> = rgba( [ from <color> ]?
        [ <number> | <percentage> | none]{3}
        [ / [<alpha-value> | none] ]?  )

相对颜色语法 rgb()rgba() 函数中, 允许的组件关键字有:

测试
在 sRGB 颜色空间中操作颜色分量:
rgb(from  indianred 255 g b)

这将获取 indianred 的 sRGB 值 (205 92 92) 并将红色分量替换为 255,得到 rgb(255 92 92)。

相对 sRGB 颜色语法适用于非旧版 RGB 句法形式。

例如,这种尝试将 rgba 旧版颜色语法与逗号一起使用的做法是错误的
rgba(from  darkblue 16, 32, b, 0.5 )
相反,应使用
rgb(from  darkblue 16 32 b / 0.5 )

这将获取 darkblue 的 sRGB 值 (0 0 139) 并替换红色、绿色和 alpha 分量,得到 rgb(16 32 139 / 0.5)

4.4. 相对 HSL 颜色

现代颜色语法hsl()hsla() 函数的语法扩展如下:

<modern-hsl-syntax> = hsl([from <color>]?
          [<hue> | none]
          [<percentage> | <number> | none]
          [<percentage> | <number> | none]
          [ / [<alpha-value> | none] ]? )
<modern-hsla-syntax> = hsla([from <color>]?
        [<hue> | none]
        [<percentage> | <number> | none]
        [<percentage> | <number> | none]
        [ / [<alpha-value> | none] ]? )

相对颜色语法 hsl()hsla() 函数中, 允许的组件关键字有:

测试
这将色相角度增加 180 度,得到互补色。
--accent:  lightseagreen;
--complement:   hsl(from var(--accent) calc(h + 180) s l);

lightseagreen 是 hsl(177deg 70% 41%),所以 --complement 是 hsl(357deg 70% 41%)

相对 HSL 颜色语法仅适用于非遗留的 HSL 语法形式。

4.5. 相对 HWB 颜色

hwb() 函数的语法被扩展如下:

hwb() = hwb([from <color>]?
        [<hue> | none]
        [<percentage> | <number> | none]
        [<percentage> | <number> | none]
        [ / [<alpha-value> | none] ]? )

相对颜色语法 hwb() 函数中, 允许的组件关键字有:

测试

4.6. 相对 Lab 颜色

lab() 函数的语法被扩展如下:

lab() = lab([from <color>]?
        [<percentage> | <number> | none]
        [<percentage> | <number> | none]
        [<percentage> | <number> | none]
        [ / [<alpha-value> | none] ]? )

相对颜色语法 lab() 函数中, 允许的组件关键字有:

多种调整基色透明度的方法:

请注意,所有调整都是无损的,因为不会发生色域剪裁,因为 lab() 涵盖所有可见颜色。 这对基于 sRGB 的函数中的 alpha 调整(例如 'rgb()'、'hsl()' 或 'hwb()')是不成立的, 这些函数还会在计算 HSL 或 HWB 之前将颜色转换为 sRGB, 并且还会调整 alpha 透明度。

完全去除颜色饱和度以获得灰色,同时保持相同的亮度:
--mycolor:  orchid;
// orchid 是 lab(62.753 52.460 -34.103)
--mygray:  lab(from var(--mycolor) l 0 0)
// mygray 是 lab(62.753 0 0)rgb(59.515% 59.515% 59.515%)

4.7. 相对 Oklab 颜色

oklab() 函数的语法被扩展如下:

oklab() = oklab([from <color>]?
          [<percentage> | <number> | none]
          [<percentage> | <number> | none]
          [<percentage> | <number> | none]
          [ / [<alpha-value> | none] ]? )

相对颜色语法 oklab() 函数中, 允许的组件关键字有:

4.8. 相对 LCH 颜色

lch() 函数的语法被扩展如下:

lch() = lch([from <color>]?
        [<percentage> | <number> | none]
        [<percentage> | <number> | none]
        [<hue> | none]
        [ / [<alpha-value> | none] ]? )

相对颜色语法 lch() 函数中, 允许的组件关键字有:

测试
lch(from peru calc(l * 0.8) c h) 生成的颜色比 peru 或 lch(62.2532% 54.0114 63.6769) 暗 20%,并保持其色度和色相不变。 结果为 lch(49.80256 54.0114 63.6769)
这将色相角度加 180 度,生成互补色。
--accent:  lightseagreen;
--complement:   lch(from var(--accent) l c calc(h + 180));

lightseagreen 是 lch(65.4937 39.4484 190.1013),因此 --complement 是 lch(65.4937 39.4484 370.1013)

完全去饱和颜色变为灰色,同时保持相同亮度:
--mycolor:  orchid;
// orchid 是 lch(62.753 62.571 326.973)
--mygray:  lch(from var(--mycolor) l 0 h);
// mygray 是 lch(62.753 0 326.973),即 rgb(59.515% 59.515% 59.515%)

但现在(由于色相被保留)再次 重新饱和

--mymuted:  lch(from var(--mygray) l 30 h);
// mymuted 是 lch(62.753 30 326.973),即 rgb(72.710% 53.293% 71.224%)

然而,不同于 HSL,操纵结果不能保证处于色域内。

在此示例中,目的是生成与原始颜色具有相同亮度和色度, 但色相角度相差 120 度的颜色。 原始颜色在 RGB 色域内, 但在 LCH 中旋转色相会生成色域外的颜色。
--mycolor:  lch(60% 90 320);
lch(from var(--mycolor) l c calc(h - 120));

这会生成一个高色度的青绿色, lch(60% 90 200) 即 color(srgb -0.6 0.698 0.772), 因此超出了 sRGB 色域(负红值)。 实际上,它也超出了 display-p3 色域: color(display-p3 -0.46 0.68 0.758), 甚至超出了 rec2020 色域: color(rec2020 -0.14 0.623 0.729)。

在 sRGB 色域内的最接近颜色为 lch(60.71% 37.56 201.1) 即 rgb(0% 64.2% 66.3%)。色度差异(37.5 代替 90)非常大。

图示 CIE CH 平面,显示相对颜色操作。 ab 轴有标记, 并在中间相交。 我们从中央亮度轴向下看。 sRGB 色域的最大色域显示为不规则的凸多边形。

此图显示了 CIE ab 平面中的 sRGB 色域。 小圆圈表示主要和次要颜色。 原始颜色(显示为大圆圈)在 sRGB 色域内; 但当 LCH 色相旋转 -120° 时变为 色域外(显示为灰色填充和红色边框)。 色域映射后的 结果色度较低。

在 HSL 中执行相同操作将返回一个色域内的结果。 但它在其他方面不尽如人意:

--mycolor:  lch(60% 90 320);
hsl(from var(--mycolor) calc(h - 120) s l);

在 HSL 中,--mycolor 是 hsl(289.18 93.136% 65.531%) 因此减去 120 度得出 hsl(169.18 93.136% 65.531%)。 将该结果转换回 LCH 时, lch(89.0345% 49.3503 178.714) 我们看到,由于 HSL 中的色相旋转, 亮度从 60% 增加到 89%, 色度从 90 降至 49, 而色相实际上改变了 141 度,而不是 120 度。

4.9. 相对 OKLCh 颜色

oklch() 函数的语法扩展如下:

oklch() = oklch([from <color>]?
          [<percentage> | <number> | none]
          [<percentage> | <number> | none]
          [<hue> | none]
          [ / [<alpha-value> | none] ]? )

相对颜色语法 oklch() 函数中, 允许的组件关键字有:

测试

因为 OKLCh 既具有感知均匀性又保留色度, 并且其轴对应于易于理解的颜色属性, 所以 OKLCh 是进行颜色操作的理想选择。

在此示例中,目标同样是生成一个具有相同亮度和色度的新颜色, 但采用三等分配色(色相相差 120 度)。 在此示例中,我们将在 OKLCh 中进行操作。 原始颜色在 RGB 色域内, 但在 OKLCh 中旋转色相 再次产生超出色域的颜色。
--mycolor:  lch(60% 90 320);
        oklch(from var(--mycolor) l c calc(h - 120));
        

--mycolor 是 oklch(0.69012 0.25077 319.893)。 从色相中减去 120 会得到一个色度非常高的蓝绿色, oklch(0.69012 0.25077 199.893) 这超出了 sRGB 色域, color(srgb -0.6018 0.7621 0.8448) 正如负红色分量所示。 通过降低 OKLCh 色度将其纳入色域,得到 oklch(0.69012 0.1173 199.893)。 OKLCh 色度已从 0.251 降至 0.117。

5. 定义预设和自定义颜色空间:color() 函数

color() 函数允许在特定的、给定的颜色空间中指定颜色(而不是大多数其他颜色函数运行所在的隐式 sRGB 颜色空间)。

在此层级,color() 函数扩展支持自定义颜色空间,除了来自CSS Color 4 § 10. 预定义颜色空间 的预定义空间外。

它还扩展支持相对颜色,而不仅仅是绝对颜色。

其语法如下:

color() = color( [from <color>]? <colorspace-params> [ / [ <alpha-value> | none ] ]? )
<colorspace-params> = [<custom-params> | <predefined-rgb-params> | <xyz-params>]
<custom-params> = <dashed-ident> [ <number> | <percentage> | none ]+
<predefined-rgb-params> = <predefined-rgb> [ <number> | <percentage> | none ]{3}
<predefined-rgb> = srgb | srgb-linear | display-p3 | a98-rgb | prophoto-rgb | rec2020
<xyz-params> = <xyz> [ <number> | <percentage> | none ]{3}
<xyz> = xyz | xyz-d50 | xyz-d65

color 函数的参数指定了一个颜色,并明确列出颜色空间。

它可以表示一个 无效颜色,如下文所述,或一个 有效颜色

任何非 无效颜色 的颜色都是 有效颜色

颜色可以是 有效颜色,但仍然超出输出设备(屏幕、投影仪或打印机)可以显示的颜色范围。此时被称为 色域外

色域外的颜色其分量值小于 0 或 0%,或大于 1 或 100%。这些值并不无效;在显示时,它们会在计算值阶段使用相对比色法映射为色域内值(0/0% 到 1/100%)。

每个 有效颜色要么在输出设备的色域内(屏幕或打印机),要么是 色域外

5.1. 相对 Color-Function 颜色

相对颜色语法 color() 函数(使用 <custom-params>)中, 允许的组件关键字的数量和名称为:

相对颜色语法 color() 函数(使用 <predefined-rgb-params>)中, 允许的组件关键字有:

相对颜色语法 color() 函数(使用 <xyz-params>)中, 允许的组件关键字有:

相对颜色语法 color() 函数(使用 <predefined-rgb-params><xyz-params>)中, 一个额外允许的组件关键字是:

参数具有以下形式:

测试
例如,在CIE XYZ D65颜色空间中使用相对颜色语法生成的颜色具有与基准颜色相同的色度,但亮度减少了一半:
--base:  color(display-p3 0.7 0.5 0.1);
--dark:  color(from var(--base) xyz-d65 calc(x/2) calc(y/2) calc(z/2));

原始颜色是color(xyz-d65 0.281 0.253 0.044),因此相对颜色是color(xyz-d65 0.14 0.126 0.022)。

5.2. 自定义颜色空间

CSS允许通过引用颜色配置文件来指定颜色。 例如,这可以用于校准的CMYK打印机、 或RGB颜色空间, 或任何已进行过特征化的彩色或单色输出设备。

本示例指定了四种校准颜色: 两种为自定义空间 (用于SWOP涂层CMYK印刷机, 和广色域的七色墨打印机), 另外两种为预定义空间 (ProPhoto RGB和display-p3 RGB空间)。 在每种情况下,数值参数范围为0.0到1.0 (而不是例如0到255)。
color: color(--swopc 0.0134 0.8078 0.7451 0.3019);
color: color(--indigo 0.0941 0.6274 0.3372 0.1647 0 0.0706 0.1216);
color: color(prophoto-rgb 0.9137 0.5882 0.4784);
color: color(display-p3 0.3804 0.9921 0.1412);

未使用预定义颜色空间的颜色 CSS Color 4 §  10. 预定义颜色空间,通过使用 <dashed-ident>来区分,并且还需要在样式表中某处提供一个匹配的 @color-profile规则, 以将名称与配置文件数据相关联。

测试
@color-profile --swopc {
  src: url('http://example.org/swop-coated.icc');}
@color-profile --indigo {
  src: url('http://example.org/indigo-seven.icc');}

5.3. 指定颜色配置文件: @color-profile at-rule

@color-profile规则定义并命名了一个颜色配置文件, 该配置文件可在稍后用于color()函数中指定颜色。

定义如下:

@color-profile = @color-profile [<dashed-ident> | device-cmyk] { <declaration-list> }
测试

<dashed-ident>提供了颜色配置文件的名称, 该名称将在CSS样式表中使用。 另一种情况是device-cmyk关键字, 这意味着如果此颜色配置文件有效, 将用于解析在device-cmyk中指定的颜色。

@color-profile规则接受本规范中定义的描述符。

名称: src
用于: @color-profile
值: <url>
初始值: n/a

src描述符指定用于检索颜色配置文件信息的URL。

检索到的ICC配置文件在以下情况下有效:

如果配置文件无效,所有引用该配置文件的CSS颜色都是无效颜色

为了获取外部颜色配置文件, 给定@color-profile规则rule, 使用rule的URL 获取样式资源, 样式表为rule父CSS样式表, 目标为"color-profile", CORS模式为"cors", processResponse的步骤如下,给定响应|/res| 和null、失败或字节流byteStream: 如果byteStream是字节流, 将颜色配置文件应用于解析后的|byteStream。

注意: ICC配置文件的互联网媒体类型 ("MIME类型") 是application/vnd.iccprofile

名称: rendering-intent
用于: @color-profile
值: 相对色度 | 绝对色度 | 可感知 | 饱和度
初始值: relative-colorimetric

颜色配置文件包含 “渲染意图”, 定义了如何色域映射它们的颜色到比其定义的范围更小的色域。 通常配置文件只包含一个意图, 但当有多个时, rendering-intent描述符选择使用其中之一。

四种可能的渲染意图是[ICC]:

相对色度
媒体相对色度渲染意图要求保留源颜色相对于各自媒体白点的不变性。 落在目标介质色域外的源颜色将被映射到色域边界上的颜色,采用多种不同的方法。

媒体相对色度渲染意图通常与黑点补偿一起使用, 其中源介质的黑点被映射到目标介质的黑点。 此方法必须将源白点映射到目标白点。 如果使用了黑点补偿,则源黑点也必须映射到目标黑点。 颜色的相对关系应在源色域和目标色域内部保持不变, 而目标色域之外的颜色可能会发生变化。

absolute-colorimetric
ICC-绝对比色法要求保留落在目标介质色域内的源颜色相对于采用的白色(完美的反射漫射体)不变。对于超出目标介质色域的源颜色,使用多种不同的方法将其映射到色域边界上的颜色。此方法可以最精确地匹配色域内的颜色,但如果目标介质的白点低于源介质的白点,则会导致高光剪切。因此,建议仅在需要精确颜色匹配且高光剪切不是问题的应用程序中使用此方法。

此方法在转换颜色时必须禁用白点匹配和黑点匹配。一般来说,除了测试目的外,不推荐使用此选项。

perceptual
这种方法通常是图像的首选,尤其是在源和目标之间存在较大差异时(例如将屏幕显示的图像再现为反射打印件)。它采用专有方法对源图像的颜色进行重新优化,以适应目标介质。这种重新优化可能会导致源色域和目标色域内的颜色发生变化,尽管感知变换应该在复制过程中保持原作的基本艺术意图。它不会尝试纠正源图像中的错误。

注意:使用v2 ICC配置文件时,没有指定的感知参考介质,这可能会导致互操作性问题。当使用v2 ICC配置文件时,除非已经检查过特定的源和目标配置文件并确保它们的组合能产生预期效果,否则更安全的方法是使用带有黑点补偿的媒体相对比色渲染意图,而不是感知渲染意图。

该方法应保持像素之间的相对颜色值,因为它们被映射到目标设备的色域中。为了避免色相偏移和不连续性,并尽可能保留场景的整体外观,该方法可能会更改最初位于目标设备色域内的像素值。

饱和度
此选项是为保持原始图像的相对饱和度(色度)以及保持纯色而创建的。然而,类似感知意图,它也经历了互操作性问题,并且由于纯色保留不适合使用参考介质解决方案,因此使用v4配置文件也无法解决问题。除非已经检查了特定的源和目标配置文件,并确保它们的组合能产生预期效果,否则不推荐使用此渲染意图。 此选项应保持原始像素的相对饱和度(色度)值。超出色域的颜色应转换为具有相同饱和度但落在色域内的颜色。
名称: components
适用对象: @color-profile
值: <ident>#
初始值: n/a

颜色配置文件可以定义包含多个组件的颜色空间。 例如,一个青色、品红、黄色和黑色(CMYK)的配置文件有四个组件,分别命名为c, m, y 和 k。 而一个四组件加法屏幕配置文件可能使用四个组件,命名为r, g, y 和 b。

该描述符的值是一个用逗号分隔的<ident>标记的列表。 每个<ident>命名一个组件, 按照它们在颜色配置文件中使用的顺序排列,而标记的总数定义了组件的数量。

该描述符声明有四个组件,分别命名为青色、品红色、黄色和黑色:
components: cyan, magenta, yellow, black

而这个描述符选择了更简洁的名称:

components: c,m,y,k
该描述符声明有七个组件,分别命名为青色、品红色、黄色、黑色、橙色、绿色和紫色:
components: cyan, magenta, yellow, black, orange, green, violet

如果一个组件与 noneASCII 不区分大小写)匹配, 则该描述符无效, 因为它会与缺失值的标记冲突。

如果为组件选择的名称与CSS Values 4 § 10.7.1 数值常量: e, pi中定义的CSS数值常量冲突, 该组件仍然有效, 但在calc()中使用时,该组件将被数值常量覆盖,导致意外结果。

该描述符不明智地将一个组件命名为pi, 导致相对颜色语法中的意外结果。
@color-profile --unwise {
  src: url(https://example.com/unwise);
  components: mi, pi, ni;
}
--base: color(--unwise 35% 20% 8%);
--accent: color(from var(--base) mi calc(pi * 2) calc(ni / 2));

在这里,--accent 的组件值为35%, 3.14159265358979 * 2 = 6.28318530717959, 4%。

5.4. CSS和打印: 使用校准的CMYK和其他印刷颜色空间

@color-profile at-rule不仅限于RGB颜色空间。 虽然屏幕通常直接以RGB显示颜色, 但打印机通常使用CMYK表示颜色。

校准的四色打印使用青色、洋红、黄色和黑色(CMYK), 或者使用更多墨水的高保真宽色域打印 如青色洋红黄色黑色橙色绿色紫色(CMYKOGV) 也可以在CSS中进行, 前提是你有一个与墨水、纸张、总墨覆盖率和设备 相对应的ICC配置文件。

例如,使用符合 ISO 12647-2:2004 / Amd 1:2007 标准的胶版印刷, 采用 FOGRA39 特性化数据, 在 115gsm 涂层纸上, 油墨限制为 300% 总区域覆盖率 [FOGRA39]
@color-profile --fogra39 {
  src: url('https://example.org/Coated_Fogra39L_VIGC_300.icc');
} 
.header { 
  background-color:  color(--fogra39 0% 70% 20% 0%); 
} 

在这里,color() 函数首先声明了我们给配置文件起的名字, 然后给出青色、洋红色、黄色和黑色的百分比。

在这个配置文件中,这解析为颜色 lab(63.673303% 51.576902 5.811058) 即 rgb(93.124%, 44.098%, 57.491%)。

由于已知特定CMYK组合的实际颜色, 可以进行打印输出的屏幕可视化(软校色)。

此外,依赖于已知颜色的程序 (例如抗锯齿、合成、使用颜色创建渐变等) 可以正常进行。

一张由彩色方块组成的网格图。有六列, 标签为A到F, 和四行, 标签为1到4。

色彩检测卡,用于确保印刷和摄影行业的色彩保真度。 每个色块都有平均测量的 Lab 值。 矩形显示的是转换为 sRGB 的 Lab 值。 几乎看不见的圆形显示的是 Lab 值, 这些值通过 FOGRA51 [FOGRA51] ICC 配置文件转换为 CMYK。 然后,CMYK 值通过相同的 ICC 配置文件反向转换, 以产生新的 Lab 值。然后将这些值转换为 sRGB 以进行显示。

第三行第一个色块的圆圈更明显, 因为该颜色稍微超出了所使用的FOGRA51 CMYK色域。

下表显示了每个色块在通过CMYK循环后 原始Lab值和Lab值之间的DeltaE 2000。 DeltaE 2000为1或更大时就能被肉眼察觉。

A B C D E F
1 0.06 0.07 0.03 0.04 0.06 0.17
2 0.03 0.75 0.05 0.06 0.03 0.02
3 1.9 0.04 0.06 0.05 0.02 0.05
4 0.03 0.08 0.03 0.03 0.04 0.80
此示例使用ISO 12647-2:2004标准的胶印, 使用CGATS/SWOP TR005 2007表征数据 在5号纸上 墨水覆盖限制为300%, 并使用中度灰色成分替换(GCR)。
@color-profile --swop5c { 
  src: url('https://example.org/SWOP2006_Coated5v2.icc'); 
} 
.header { 
  background-color:   color(--swop5c 0% 70% 20% 0%); 
} 

在这个配置文件中,给定的CMYK百分比 (与上一个例子相同) 解析为颜色 lab(64.965217% 52.119710 5.406966) 即 rgb(94.903%, 45.248%, 59.104%)。

可以指定备用颜色, 例如使用媒体查询, 以防指定的CMYK颜色已知超出sRGB色域。

此示例使用之前相同的FOGRA39设置, 但指定了一个超出sRGB色域的亮绿色。 然而,它在display-p3色域内。 因此,在宽色域屏幕上和打印时按原样显示, 在sRGB屏幕上则使用较不鲜艳的备用颜色。
@media (color-gamut: srgb) { 
  .header { 
    background-color:   rgb(8.154% 60.9704% 37.184%); 
    } 
} 
@media print, (color-gamut: p3){ 
  .header { 
    background-color:   color(--fogra39 90% 0% 90% 0%); 
    } 
} 

该CMYK颜色对应于lab(56.596645% -58.995875 28.072154) 或lch(56.596645% 65.33421077211648 154.5533771086801)。 在sRGB中,这将是rgb(-60.568% 62.558% 32.390%),如大负红分量所示, 超出了色域。

减少色度直到结果在色域内 给出 lch(56.596645% 51 154.5533771086801) 这是 rgb(8.154% 60.9704% 37.184%), 这已被手动指定为备用颜色。

对于宽色域屏幕,颜色在display-p3色域内 (即display-p3(0.1658 0.6147 0.3533))。

颜色不限于四种墨水(CMYK)。例如,可以使用宽色域7色墨水集。

此示例使用 beta FOGRA55 数据集 [FOGRA55] 用于 CMYKOGV 七色印刷。 其中四种油墨——黑色、青色、品红色和黄色——与 FOGRA51 套装中的油墨相同, 并产生相同的结果。 另外三种油墨是:

测量条件为 M1, 这意味着已考虑纸张中的荧光增白剂, 并且分光光度计没有紫外线截止滤光片。

@color-profile --fogra55beta {
  src: url('https://example.org/2020_13.003_FOGRA55beta_CL_Profile.icc');
}
.dark_skin {
  background-color: 
  color(--fogra55beta 0.183596 0.464444 0.461729 0.612490 0.156903 0.000000 0.000000);
}
.light_skin {
  background-color: 
  color(--fogra55beta 0.070804 0.334971 0.321802 0.215606 0.103107 0.000000 0.000000);
}
.blue_sky {
  background-color: 
  color(--fogra55beta 0.572088 0.229346 0.081708 0.282044 0.000000 0.000000 0.168260);
}
.foliage {
  background-color: 
  color(--fogra55beta 0.314566 0.145687 0.661941 0.582879 0.000000 0.234362 0.000000);
}
.blue_flower {
  background-color: 
  color(--fogra55beta 0.375515 0.259934 0.034849 0.107161 0.000000 0.000000 0.308200);
}
.bluish_green {
  background-color: 
  color(--fogra55beta 0.397575 0.010047 0.223682 0.031140 0.000000 0.317066 0.000000);
}

5.5. 将 CMYK 颜色转换为 Lab

从校准的 CMYK 颜色空间到 Lab 的转换 通常是通过在 ICC 配置文件中查找 Lab 值来完成的。

5.6. 将 Lab 颜色转换为 CMYK

对于打印, Lab 颜色需要转换为打印机的颜色空间。

这通常是通过在 ICC 配置文件中查找 CMYK 值来完成的。

6. 未校准的 CMYK 颜色: device-cmyk() 函数

有时,当某个打印机未进行校准时, 但通过实验或通过打印样本色卡已知某些墨水组合的输出结果时, 以设备相关的方式表示 CMYK 颜色会很有用。

注意: 由于实际结果颜色可能未知, CSS 处理器可能会尝试对其进行近似。 这种近似可能与实际的打印结果在视觉上相差很大。

device-cmyk() 函数允许作者以这种方式指定颜色:

device-cmyk() = <legacy-device-cmyk-syntax> | <modern-device-cmyk-syntax>
<legacy-device-cmyk-syntax> = device-cmyk( <number>#{4} )
<modern-device-cmyk-syntax> = device-cmyk( <cmyk-component>{4} [ / [ <alpha-value> | none ] ]? )
<cmyk-component> = <number> | <percentage> | none

device-cmyk() 函数的参数依次指定青色、洋红色、黄色和黑色成分, 其值为0到1之间的数字, 或者在现代语法中,为0%到100%之间的百分比。 这两种用法是等价的,且线性映射。 小于0或0%的值,或大于1或100%的值, 并非无效; 相反,它们将在计算值时被限定为0/0%或1/100%。

在现代语法中,第五个参数指定颜色的 alpha 分量。 它的解释与 rgb() 函数的第四个参数完全相同。 如果省略,则默认为 100%

由于 历史原因device-cmyk() 还支持 旧版颜色语法

通常,基于打印的应用程序实际上会将使用的颜色存储为 CMYK, 并以这种形式将其发送到打印机。 但是,这些颜色没有色度解释, 因此不能用于渐变、合成、混合等。

因此,设备 CMYK 颜色必须转换为等效颜色。 这并不简单,像从 HSL 或 HWB 到 RGB 的转换一样; 精确的转换取决于输出设备的精确特性。

  1. 如果用户、作者或用户代理样式表 对 device-cmyk 有 @color-profile 定义, 且可以检索到 src 描述符指定的资源, 且资源是有效的 CMYK ICC 配置文件, 且用户代理能够处理 ICC 配置文件, 则 device-cmyk() 函数的计算值 必须是 CMYK 颜色的 Lab 值。
  2. 否则, device-cmyk() 函数的计算值必须是 CMYK 颜色的 sRGB 值, 按照以下简单的转换算法转换。
例如,没有 @color-profile 时, 使用简单转换,以下颜色是等效的。
color:  device-cmyk(0 81% 81% 30%);
    color:  rgb(178 34 34);
    color:  firebrick;
在示例样式表中指定了 @color-profile 时, 使用色度转换,以下颜色是等效的。
color:  device-cmyk(0 81% 81% 30%);
color:  lab(45.060% 45.477 35.459)
color:  rgb(70.690% 26.851% 19.724%);

简单转换必然是近似的, 因为它不了解墨水的色度、 点增益、 RGB 空间的色度等。

一个彩色方块网格。共有六列, 标签为 A 到 F, 四行, 标签为 1 到 4。

一个色卡,用于确保打印和摄影行业的色彩保真度。 每个色块的平均测量 Lab 值都可用。 矩形显示了 Lab 值,转换为 sRGB。 圆圈显示了 Lab 值,通过 ICC 配置文件转换为 CMYK。 然后,CMYK 值被简单地转换为 sRGB。

下表显示了每个色块的 DeltaE 2000, 即经过 CMYK 往返后原始 Lab 和 Lab 值之间的差异。 DeltaE 2000 大于或等于 1 则可以被肉眼察觉,而大于 5 则完全是不同的颜色。

A B C D E F
1 11.33 9.36 5.66 7.52 12.39 21.58
2 6.40 8.79 11.77 17.16 11.91 3.97
3 12.1 17.00 3.38 1.94 18.08 14.97
4 1.89 6.56 7.85 8.76 9.82 10.29

6.1. 在未校准的 CMYK 和基于 sRGB 的颜色之间进行简单转换

简单地从 CMYK 转换为 RGBA

简单地从 RGBA 转换为 CMYK

7. 响应使用的颜色方案:light-dark() 函数

系统颜色能够响应当前使用的 color-scheme 值。 light-dark() 函数向作者公开了相同的功能。

light-dark() = light-dark( <color>, <color> )

如果 使用的颜色方案light 或未知, 则该函数计算为第一个颜色的计算值; 如果 使用的颜色方案dark,则计算为第二个颜色的计算值。

测试

8. 动态指定具有足够对比度的文本颜色:contrast-color() 函数

当动态创建颜色时,将其用作背景色时,指定一个能提供足够对比度的文本颜色通常是一个挑战。 contrast-color() 函数在指定颜色用作纯色背景上的文本颜色时,会自动提供一个保证颜色对比度的颜色。

注意:易读性是一个复杂的问题,足够的颜色对比度只是其中的一部分。 拥有一对具有足够对比度的颜色并不能保证文本一定易读, 因为这还取决于多种因素,例如字体、文本大小、 周围颜色等。

contrast-color() = contrast-color( <color> )
        

contrast-color() 解析为 whiteblack, 以当输入颜色用作纯色背景时,能为文本产生最大颜色对比度的那个为准。 如果 whiteblack 产生相同的对比度, 则解析为 white

用于确定输出浅色还是深色的精确颜色对比度算法在此级别由用户代理 (UA) 定义。

注意:此规范的未来版本预计将引入更多对所使用的对比度算法、用例以及返回颜色的控制。

建议用户代理不要简单地使用 WCAG 2.1 第 1.4.3 节 对比度 (最低) 的对比度算法来决定浅色和深色,因为它存在几个已知问题。 但是,此函数返回的颜色仍应满足 WCAG 2.1 第 1.4.3 节 对比度 (最低) 对 AA 大号文本的要求,因为许多作者需要满足强制执行此要求的法律规定。

9. 颜色插值

9.1. 插值的颜色空间

<color-interpolation-method> 已扩展为允许使用 自定义颜色空间

<color-space> = <rectangular-color-space> | <polar-color-space> | <custom-color-space>
<rectangular-color-space> = srgb | srgb-linear | display-p3 | a98-rgb | prophoto-rgb | rec2020 | lab | oklab | xyz | xyz-d50 | xyz-d65
<polar-color-space> = hsl | hwb | lch | oklch
<custom-color-space> = <dashed-ident>
<hue-interpolation-method> = [ shorter | longer | increasing | decreasing ] hue
<color-interpolation-method> = in [ <rectangular-color-space> | <polar-color-space> <hue-interpolation-method>? | <custom-color-space> ]

<dashed-ident> 必须已在有效的 @color-profile 规则中声明, 否则 <color-interpolation-method> 无效。

10. 解析 <color>

10.1. 解析 color-mix()

如果所有 <color> 参数解析为其各自颜色空间中的对应颜色, 则计算值为混合后的颜色, 在指定的混合颜色空间中, 按照 CSS Color 4 §  14. 解析 <color> 值 的方法解析。 否则(如果 currentColor 在函数中使用), 计算值为 color-mix() 函数, 并且每个 <color> 参数按照 CSS Color 4 §  14. 解析 <color> 值 的方法解析, 以此保持继承到子元素。

测试

10.2. 解析相对颜色语法值

如果所有 <color> 参数解析为其各自颜色空间中的对应颜色, 则计算值为绝对 <color> 值, 在指定的 RCS 颜色空间中, 按照 CSS Color 4 §  14. 解析 <color> 值 的方法解析。

测试

否则(如果 currentColor 在函数中使用), 计算值为相对颜色语法函数, 其源 <color> 参数根据 CSS Color 4 §  14. 解析 <color> 值 的方法解析, 以此保持继承到子元素。

测试

10.3. 解析 device-cmyk

计算值和使用值 是指定的设备特定 CMYK 颜色, (其分量为 <number>,而不是 <percentage>) 与指定的 alpha 分量配对 (作为 <number>,而不是 <percentage>; 如果未指定,则默认为不透明)。

实际值 可能根据操作而有所不同; 对于支持 CMYK 的设备,可以呈现为 CMYK 颜色; 对于与非 CMYK 颜色的混合或在非 CMYK 设备上渲染时, 必须按 § 6 未校准的 CMYK 颜色:device-cmyk() 函数 中的规定进行转换。

例如,
 device-cmyk(0% 70% 20% 0%)

具有指定值和实际值

 device-cmyk(0 0.7 0.2 0)

如果实现支持 ICC 配置文件并安装了合适的配置文件, 则使用的值将是

 lab(63.673% 51.577 5.811)

注意:与所有颜色一样,使用值不可通过脚本获取。

11. 序列化

本节扩展了 CSS Color 4 §  15. 序列化 <color> 值,添加了 color-mix()device-cmyk(), 和相对颜色函数的序列化结果。

在本节中,规范中使用的字符串及其对应字符如下。

字符串 字符
" " U+0020 空格
"," U+002C 逗号
"-" U+002D 连字符-减号
"." U+002E 句号
"/" U+002F 斜杠

字符串“.”应作为小数点分隔符使用, 无论地区如何,并且不应使用千位分隔符。

通常情况下, 如果结果的 alpha 值正好为 1, 它将在序列化时省略; 默认隐含值为 1(完全不透明)。

11.1. 序列化 color-mix()

color-mix() 函数声明值的序列化是字符串 "color-mix(in ", 后跟指定的<color-space>(全小写), 后跟 ", ", 后跟第一个指定的颜色, 后跟一个空格, 后跟第一个百分比的序列化(见下文), 后跟 ", ", 后跟第二个指定的颜色, 后跟第二个百分比的序列化(见下文), 后跟 ")"。

color-mix() 函数声明值的第一个百分比的序列化定义如下:

color-mix() 函数声明值的第二个百分比的序列化定义如下:

注意:calc() 值 被认为是未知的, 因此永远不会等于 50%, 也永远不会与其他值相加等于 100%。

例如,声明值的序列化
color-mix(in oklab, teal, peru 40%)

将是字符串 "color-mix(in oklab, teal 60%, peru)"。

声明值的序列化

color-mix(in oklab, teal 50%, peru 50%)

将是字符串 "color-mix(in oklab, teal, peru)"。

声明值的序列化

color-mix(in oklab, teal 70%, peru 70%)

将是字符串 "color-mix(in oklab, teal 70%, peru 70%)"。 因为这些在百分比归一化后才发现归一化为 50%。

color-mix() 函数结果的序列化 取决于混合中是否使用了关键字 currentColor。 如果是,则结果序列化为声明值。 这允许在 color 属性具有不同值的子元素上使用正确的混合。 否则,它是一个 <color>, 如 CSS 颜色 4 § 15. 序列化 <color> 值 中所定义。 使用的形式取决于用 "in" 指定的颜色空间:

混合颜色空间 形式
srgb color(srgb r g b)
srgb-linear color(srgb-linear r g b)
display-p3 color(display-p3 r g b)
a98-rgb color(a98-rgb r g b)
prophoto-rgb color(prophoto-rgb r g b)
rec2020 color(rec2020 r g b)
hsl color(srgb r g b)
hwb color(srgb r g b)
xyz-d65 color(xyz-d65 x y z)
xyz-d50 color(xyz-d50 x y z)
xyz color(xyz-d65 x y z) ¹
lab lab(l a b)
lch lch(l c h)
oklab oklab(l a b)
oklch oklch(l c h)
¹
因为 xyz 只是 xyz-d65 的别名
测试

对回传的最小精度与 CSS Color 4 §  15. 序列化 <color> 值 中指定的精度相同。

颜色混合的结果
color-mix(in lch, peru 40%, palegoldenrod)

序列化为字符串 "lch(79.7256 40.448 84.771)", 而颜色混合的结果

color-mix(in srgb, peru 40%, palegoldenrod)

序列化为字符串 "color(srgb 0.8816 0.7545 0.4988)"。

11.2. 序列化原始颜色

在另一个颜色函数内部用作原始颜色的声明值的颜色,作为声明值组件的序列化方式如下:

  1. 对于 rgb()rgba()hsl()hsla()

注意:无论使用现代语法还是旧式语法,都使用相同的序列化方式。

  1. 对于 hwb()lab()lch()oklab()oklch()

  1. 对于 color()

11.3. 序列化相对颜色函数

相对颜色的声明值的序列化方式如下:

  1. 对于 rgb()rgba()hsl()hsla()

  1. 对于 hwb()lab()lch()oklab()oklch()

  1. 对于 color()

例如,声明值
OkLcH(from peru  l    c  h)

的序列化是字符串 "oklch(from peru l c h)"

例如,声明值
rgb(from red calc(r / 2) g calc(30%));

的序列化是字符串 "rgb(from red calc(0.5 * r) g calc(30%))", 而计算值的序列化 是字符串 "color(srgb 0.5 0 0.3)"。

例如,声明值
hsl(from hsl(none 10% 50%) h s l);

的序列化是字符串 "hsl(from hsl(none 10% 50%) h s l)", 而计算值的序列化 是字符串 "color(srgb 0.55 0.45 0.45)"。

例如,声明值
hsl(from hsl(127.9 302% 25.33%) h s l);

的序列化是字符串 "hsl(from hsl(127.9 302% 25.33%) h s l)", 而计算值的序列化 是字符串 "color(srgb -0.511666 1.018266 -0.310225)"。

给定以下 HTML(注意在此元素上设置的 color 属性):
<div id="example" 
    style="background-color: rgb(from currentcolor r g calc(b / 2)); 
  color: blue;">
</div>

background-color 的声明值的序列化是字符串 "rgb(from currentcolor r g calc(b / 2))", 而计算值的序列化 是字符串 "color(srgb 0 0 0.5)"

相对颜色函数结果的序列化 取决于关键字 currentColor 是否是原始颜色。 如果是,则结果序列化为声明值。 这允许在 color 属性具有不同值的子元素上使用正确的值。 否则,它 是解析值, 它是一个 <color>, 如 CSS 颜色 4 § 15. 序列化 <color> 值 中所定义。

使用的形式 取决于相对颜色的颜色空间:

混合颜色空间 形式
srgb color(srgb r g b)
srgb-linear color(srgb-linear r g b)
display-p3 color(display-p3 r g b)
a98-rgb color(a98-rgb r g b)
prophoto-rgb color(prophoto-rgb r g b)
rec2020 color(rec2020 r g b)
hsl color(srgb r g b)
hwb color(srgb r g b)
xyz-d65 color(xyz-d65 x y z)
xyz-d50 color(xyz-d50 x y z)
xyz color(xyz-d65 x y z)
lab lab(l a b)
lch lch(l c h)
oklab oklab(l a b)
oklch oklch(l c h)
测试

往返的最低精度 与 CSS 颜色 4 § 15.5 序列化 color() 函数的值 中指定的精度相同。

序列化
lch(from peru calc(l * 0.8) calc(c * 0.7) calc(h + 180)) 

的结果是字符串 "lch(49.80224 37.80819 243.6803)"

11.4. 序列化自定义颜色空间

color() 组件值的保留精度, 因此序列化值中保留的有效数字位数, 在本规范中未定义, 但对于 CMYK 颜色空间,必须至少足以进行八位精度的值回传; 这将导致至少保留两位小数, 除非已省略了末尾的零。

以下颜色的序列化值是

@color-profile --swop5c {src: url('https://example.org/SWOP2006_Coated5v2.icc');
}
.header {
background-color:    color(--swop5c  0% 70.0% 20.00% .0%);
}

字符串 "color(--swop5c 0 0.7 0.2 0)"

11.5. 序列化 device-cmyk

device-cmyk() 值的序列化形式 来源于计算值,并使用 device-cmyk() 形式, 函数名为小写字母。

组件值以十进制序列化, 作为 <number>。 单个 ASCII 空格字符 " " 必须用作组件值之间的分隔符。

任何组件值中的尾随小数零必须被省略; 如果小数部分全部为零, 小数点也必须被省略。

颜色的序列化值是

  device-cmyk(0 81% 81% 30%)

字符串 "device-cmyk(0 0.81 0.81 0.3)"

device-cmyk() 组件值的保留精度, 因此序列化值中的有效数字位数, 在本规范中未定义, 但至少应足以进行八位精度的值回传; 这将导致至少两位小数, 除非尾随零已被省略。 值必须向上舍入,而不是截断。

单位 alpha 值不显式序列化。 非单位 alpha 值必须显式序列化, 且字符串 " / " (一个 ASCII 空格,后跟斜杠,再跟另一个空格) 必须用于分隔黑色 ("k") 颜色组件值 与 alpha 值。

12. API 接口

12.1. CSSColorProfileRule 接口

CSSColorProfileRule 接口表示 @color-profile 规则。

[Exposed=Window]
interface CSSColorProfileRule : CSSRule {
  readonly attribute CSSOMString name ;
  readonly attribute CSSOMString src ;
  readonly attribute CSSOMString renderingIntent ;
  readonly attribute CSSOMString components ;
};
name, 类型为 CSSOMString,只读
name 属性获取时必须返回 一个包含关联规则中定义的 颜色 配置文件name 序列化的 CSSOMString 对象。
src, 类型为 CSSOMString,只读
renderingIntent, 类型为 CSSOMString,只读
components, 类型为 CSSOMString,只读
其余的属性在获取时必须返回包含 与关联规则关联的描述符的序列化 CSSOMString 对象。 如果未在关联规则中指定描述符, 则该属性必须返回一个空字符串。

13. 默认样式规则

以下样式表是说明性的,而非规范性的。此样式表可由实现作为其默认 HTML 系列文档样式的一部分。

/* 传统桌面用户代理的超链接颜色 */
:link { color: LinkText; }
:visited { color: VisitedText; }
:active { color: ActiveText; }

/* device-cmyk 的合理、保守的默认值 */
@color-profile device-cmyk {
  src: url('https://drafts.csswg.org/css-color-4/ICCprofiles/Coated_Fogra39L_VIGC_300.icc');
}

14. 安全性考量

本规范为 CSS 增加了按需下载 ICC 配置文件的功能。 这些文件不包含可执行代码,因此不会构成增加的安全风险。

15. 隐私考量

本规范未报告任何新的隐私考量。

16. 无障碍注意事项

本规范添加了一种方法,以确保背景为用户指定颜色(包括动态颜色)的文本具有足够的对比度。

17. 变更记录

17.1. 2024 年 2 月 29 日工作草案以来的变更

17.2. 2022 年 6 月 28 日工作草案以来的变更

17.3. 2022 年 4 月 28 日工作草案以来的变更

17.4. 2021 年 12 月 15 日工作草案以来的变更

17.5. 2021 年 6 月 1 日工作草案以来的变更

17.6. 2020 年 6 月 10 日首次公开发布工作草案 (FPWD)以来的变更

17.7. 与 CSS 颜色 4 的区别

与 CSS 颜色 4 相比,一个主要变化是 CSS 颜色不再局限于 预定义的 RGB 空间,例如 sRGB 或 display-p3。

为了支持这一点,添加了几个全新的功能:

  1. color() 函数通过 @color-profile @规则进行扩展,用于配置文件相关的设备颜色, 包括校准的 CMYK。
  2. device-cmyk() 函数,用于在输出设备特定的 CMYK 颜色空间中指定未校准的颜色。

此外,新的 color-mix() 函数允许在指定的颜色空间中混合两种颜色, 以产生一种新的颜色。

符合性

文档约定

符合性要求通过描述性断言和 RFC 2119 术语的组合来表达。关键字“必须”、“禁止”、“需要”、“应”、“不应”、“推荐”、“可以”和“可选”在本文件的规范部分中应按照 RFC 2119 的描述进行解释。然而,为了可读性,这些词在本规范中不会全部以大写字母形式出现。

本规范的所有文本均为规范性内容,除非明确标记为非规范性部分、示例和注释。[RFC2119]

本规范中的示例以“例如”开头,或与规范性文本分开设置 class="example",例如:

这是一个信息性示例。

信息性注释以“注释”开头,并与规范性文本分开设置 class="note",例如:

注释,这是一条信息性注释。

建议是规范性部分,样式设计为引起特别注意,并与其他规范性文本分开设置 <strong class="advisement">,例如: 用户代理必须提供可访问的替代方案。

测试

与本规范内容相关的测试可能会记录在像这样的“测试”块中。任何此类块均为非规范性内容。


符合性类别

本规范的符合性定义了三类符合性类别:

样式表
一个 CSS 样式表
渲染器
一个 用户代理(UA),其解释样式表的语义并渲染使用它们的文档。
创作工具
一个 用户代理(UA),其编写样式表。

如果样式表中使用的所有语法声明都符合该模块定义的通用 CSS 语法及各个特性的语法,则样式表符合本规范。

如果渲染器除了按照适用的规范解释样式表外,还通过正确解析并相应地渲染文档来支持本规范定义的所有特性,则该渲染器符合本规范。然而,由于设备的限制而无法正确渲染文档的 UA 并不因此而不符合规范。(例如,UA 并不要求在单色显示器上渲染颜色。)

如果创作工具编写的样式表在语法上符合通用 CSS 语法及该模块中定义的各个特性,并且符合该模块描述的样式表的所有其他符合性要求,则该创作工具符合本规范。

部分实现

为了让作者可以利用前向兼容的解析规则来分配回退值,CSS 渲染器必须将任何不支持的 at-rules、属性、属性值、关键字和其他语法结构视为无效并适当地忽略。特别是,用户代理不得在单个多值属性声明中选择性忽略不支持的组件值并保留支持的值:如果任何值被视为无效(因为不支持的值必须如此),CSS 规定整个声明应被忽略。

不稳定和专有特性的实现

为了避免与未来稳定的 CSS 特性发生冲突,CSS 工作组建议遵循最佳实践来实现不稳定的特性和专有扩展

非实验性实现

一旦规范进入候选推荐阶段,就可以进行非实验性实现,实施者应发布任何符合 CR 级别特性的非前缀实现,前提是可以证明该实现按照规范正确实现。

为了建立和维护 CSS 在不同实现中的互操作性,CSS 工作组要求非实验性 CSS 渲染器在发布任何 CSS 特性的非前缀实现之前向 W3C 提交一个实现报告(如有必要,还包括该实现报告使用的测试用例)。提交给 W3C 的测试用例将由 CSS 工作组进行审查和修正。

有关提交测试用例和实现报告的进一步信息,请访问 CSS 工作组的网站 https://www.w3.org/Style/CSS/Test/。问题应提交到 public-css-testsuite@w3.org 邮件列表。

索引

本规范定义的术语

引用定义的术语

参考文献

规范性引用

[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 层叠与继承第五级. 2022 年 1 月 13 日. CR. URL: https://www.w3.org/TR/css-cascade-5/
[CSS-COLOR-4]
Chris Lilley; Tab Atkins Jr.; Lea Verou. CSS 颜色模块 第四级. 2024 年 2 月 13 日. CRD. URL: https://www.w3.org/TR/css-color-4/
[CSS-COLOR-ADJUST-1]
Elika Etemad; 等. CSS 颜色调整模块 第一级. 2022 年 6 月 14 日. CRD. URL: https://www.w3.org/TR/css-color-adjust-1/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS 语法模块第三级. 2021 年 12 月 24 日. CRD. URL: https://www.w3.org/TR/css-syntax-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位模块 第四级. 2024 年 3 月 12 日. WD. URL: https://www.w3.org/TR/css-values-4/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS 对象模型 (CSSOM). 2021 年 8 月 26 日. WD. URL: https://www.w3.org/TR/cssom-1/
[FETCH]
Anne van Kesteren. Fetch 标准. 动态标准. URL: https://fetch.spec.whatwg.org/
[ICC]
ICC.1:2022 (配置文件版本 4.4.0.0). 2022 年 5 月. URL: http://www.color.org/specification/ICC.1-2022-05.pdf
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 标准. 动态标准. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. RFC 中用于指示需求级别的关键字. 1997 年 3 月. 最佳实践. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. 动态标准. URL: https://webidl.spec.whatwg.org/

参考资料

[FOGRA39]
ISO 12647-2:2004 / Amd 1, 根据 ISO 12647-2 的胶印商业和特种印刷,纸张类型 1 或 2(光面或哑光铜版胶印纸, 115 g/m²),加网线数 60/cm. 2006. URL: https://www.color.org/chardata/FOGRA39.xalter
[FOGRA51]
ISO 12647-2:2013, 半色调分色、打样和生产印刷的工艺控制第 2 部分:胶印平版印刷工艺,PS 1,高级铜版纸,115 g/m²,中等承印物荧光. 2015. URL: https://www.color.org/chardata/fogra51.xalter
[FOGRA55]
基于 CMYKOGV 的色域交换空间. 2021. URL: https://fogra.org/en/research/prepress-technology/multiprimary-printing-13003

属性索引

未定义属性。

@color-profile 描述符

名称 初始值
components <ident># n/a
rendering-intent relative-colorimetric | absolute-colorimetric | perceptual | saturation relative-colorimetric
src <url> n/a

IDL 索引

[Exposed=Window]
interface CSSColorProfileRule : CSSRule {
  readonly attribute CSSOMString name ;
  readonly attribute CSSOMString src ;
  readonly attribute CSSOMString renderingIntent ;
  readonly attribute CSSOMString components ;
};