CSS color-mix()

Adam Argyle
Adam Argyle

借助 CSS color-mix() 函数,您可以直接从 CSS 中混合任何受支持的颜色空间中的颜色。

浏览器支持

  • Chrome:111.
  • Edge:111。
  • Firefox:113。
  • Safari:16.2。

来源

color-mix() 之前,若要使颜色变深、变浅或去饱和,开发者需要对颜色通道使用 CSS 预处理器或 calc()

使用 SCSS 之前
.color-mixing-with-sass {
  /* Sass: equally mix red with white */
  --red-white-mix: color.mix(red, white);
}

Sass 在 CSS 颜色规范方面做了大量工作,一直走在前沿。不过,在 CSS 中混合颜色一直没有真正的方法。如需接近,您需要对部分颜色值进行数学运算。下面是一个简化示例,展示了 CSS 如何模拟目前的混合效果:

使用 HSL 之前
.color-mixing-with-vanilla-css-before {
  --lightness: 50%;
  --red: hsl(0 50% var(--lightness));

  /* add "white" to red
     by adding 25% to the lightness channel
  */
  --lightred: hsl(0 50% calc(var(--lightness) + 25%);
}

color-mix() 为 CSS 带来了混合颜色的能力。开发者可以选择要混合到哪个色彩空间中,以及每种颜色在混合中的主导地位。

之后
.color-mixing-after {
  /* equally mix red with white */
  --red-white-mix: color-mix(in oklab, red, white);

  /* equally mix red with white in srgb */
  --red-white-mix-srgb: color-mix(in srgb, red, white);
}

这正是我们想要的。灵活、强大且功能齐全的 API。太好了,

在 CSS 中混合颜色

CSS 存在于多色彩空间和色域世界中,因此,指定混合颜色的色彩空间不是可选操作。此外,不同的色彩空间可能会极大地改变混合结果,因此了解色彩空间的效果有助于您获得所需的结果。

如需以互动方式了解相关信息,请试用此 color-mix() 工具: - 探索每种色彩空间的效果。 - 探索在圆柱形色彩空间(lchoklchhslhwb)中混合颜色时的色相插值效果。 - 点击顶部的任一颜色框,即可更改要混合的颜色。 - 使用滑块更改混合比例。 - 生成的 color-mix() CSS 代码位于底部。

在各种色彩空间中混合

混合(和渐变)的默认色彩空间为 oklab。它会提供一致的结果。您还可以指定备用颜色空间,以便根据需要定制混色。

blackwhite 为例。它们混合使用的色彩空间不会产生太大的影响,对吗?错误。

color-mix(in srgb, black, white);
color-mix(in srgb-linear, black, white);
color-mix(in lch, black, white);
color-mix(in oklch, black, white);
color-mix(in lab, black, white);
color-mix(in oklab, black, white);
color-mix(in xyz, black, white);
7 种颜色空间(srgb、Linear-srgb、lch、oklch、lab、oklab、xyz)分别显示了黑白混合的效果。图中显示了大约 5 种不同的色调,表明每种颜色空间甚至会以不同的方式混合到灰色。
试用演示版

这确实有很大的影响!

我们再以 bluewhite 为例。我之所以专门这样做,是因为这样的话,颜色空间的形状会影响结果。在本例中,大多数色彩空间在从白色转变为蓝色时会变为紫色。它还展示了 oklab 为何是如此可靠的混合颜色空间,它最接近大多数人对混合白色和蓝色(无紫色)的预期。

color-mix(in srgb, blue, white);
color-mix(in srgb-linear, blue, white);
color-mix(in lch, blue, white);
color-mix(in oklch, blue, white);
color-mix(in lab, blue, white);
color-mix(in oklab, blue, white);
color-mix(in xyz, blue, white);
7 种颜色空间(srgb、Linear-srgb、lch、oklch、lab、oklab、xyz),每个颜色空间显示不同的结果。许多都是粉色或紫色,很少有仍是蓝色的。
试用演示

了解使用 color-mix() 的颜色空间的影响对于制作渐变也是很有帮助的。Color 4 语法还允许渐变指定颜色空间,其中渐变显示的是空间区域内的混合。

.black-to-white-gradient-in-each-space {
  --srgb: linear-gradient(to right in srgb, black, white);
  --srgb-linear: linear-gradient(to right in srgb-linear, black, white);
  --lab: linear-gradient(to right in lab, black, white);
  --oklab: linear-gradient(to right in oklab, black, white);
  --lch: linear-gradient(to right in lch, black, white);
  --oklch: linear-gradient(to right in oklch, black, white);
  --hsl: linear-gradient(to right in hsl, black, white);
  --hwb: linear-gradient(to right in hwb, black, white);
  --xyz: linear-gradient(to right in xyz, black, white);
  --xyz-d50: linear-gradient(to right in xyz-d50, black, white);
  --xzy-d65: linear-gradient(to right in xyz-d65, black, white);
}
不同颜色空间中的黑色到白色渐变。
试用演示版

如果您想知道哪种色彩空间是“最佳”色彩空间,那么答案是没有。因此,我们提供了这么多选项!也不会有新的颜色空间被发明(请参阅 oklchoklab),只要有一个是“最佳”的颜色空间。每种色彩空间都有独特的闪光时刻,都是正确的选择。

例如,如果您想要获得鲜艳的混合结果,请使用 hsl 或 hwb。在以下演示中,将两种鲜艳的颜色(洋红色和黄绿色)混合在一起,hsl 和 hwb 都会产生鲜艳的结果,而 srgb 和 oklab 会产生不饱和的颜色。

混合结果如上一段所述。
试用演示版

如果想保持细微的一致性,请使用 oklab。在以下混合蓝色和黑色的演示中,hsl 和 hwb 会产生过于鲜艳且色调偏移的颜色,而 srgb 和 oklab 会产生更深的蓝色。

混合结果如上文所述。
试用演示版

花五分钟时间使用 color-mix() Playground 测试不同的颜色和空间,您就会开始了解每个空间的优势。此外,随着我们在界面中适应颜色空间的潜力,我们还会提供更多有关颜色空间的指导。

调整色调插值方法

如果您已选择混合使用圆柱形颜色空间(基本上是任何具有接受角度的 h 色调通道的颜色空间),您可以指定插值是否采用 shorterlongerdecreasingincreasing。如需了解详情,请参阅此高清色彩指南

这里给出的是同一蓝到白混合示例,但这一次,它只位于采用不同色相插值方法的圆柱形空间中。

混合结果如上文所述。
试用演示

下面是另一个 Codepen,用于帮助直观呈现色相插值,但专门针对渐变。我认为这可以帮助您了解在指定色相插值的情况下,每种颜色空间如何生成其混合结果,不妨做个研究吧!

混合使用不同的颜色语法

到目前为止,我们主要混合使用了 CSS 命名颜色,例如 bluewhite。CSS 颜色混合功能已支持混合来自两个不同颜色空间的颜色。这也是为混合指定色彩空间至关重要的另一个原因,因为它会在两种颜色不在同一色彩空间时设置公共色彩空间。

color-mix(in oklch, hsl(200deg 50% 50%), color(display-p3 .5 0 .5));

在上面的示例中,hsldisplay-p3 将转换为 oklch,然后进行混合。非常酷且灵活。

调整混合比率

您每次混合颜色时都希望每种颜色占据相同的比例,这不太可能,就像目前的大多数示例所展示的那样。好消息是,有一个语法可用于说明最终混合中每种颜色的比例。

在开始本主题之前,我们先来看一些等效的混音示例(来自规范):

.ratios-syntax-examples {
  /* omit the percentage for equal mixes */
  color: color-mix(in lch, purple, plum);
  color: color-mix(in lch, plum, purple);

  /* percentage can go on either side of the color */
  color: color-mix(in lch, purple 50%, plum 50%);
  color: color-mix(in lch, 50% purple, 50% plum);

  /* percentage on just one color? other color gets the remainder */
  color: color-mix(in lch, purple 50%, plum);
  color: color-mix(in lch, purple, plum 50%);

  /* percentages > 100% are equally clamped */
  color: color-mix(in lch, purple 80%, plum 80%);
  /* above mix is clamped to this */
  color: color-mix(in lch, purple 50%, plum 50%);
}

我发现这些示例很好地说明了极端情况。第一组示例展示了 50% 不是必需的,但可以选择指定。最后一个示例展示了一个有趣的情况:当比率相加超过 100% 时,它们会被等同地限制为总计 100%。

另请注意,如果只有一种颜色指定了比例,则系统会假定另一种颜色为 100% 的余数。下面再举几个示例来说明这种行为。

color-mix(in lch, purple 40%, plum) /* plum assigned 60% */
color-mix(in lch, purple, 60% plum) /* purple assigned 40% */
color-mix(in lch, purple 40%, plum 60%) /* no auto assignments */

以下示例说明了两条规则: 1. 如果比率超过 100%,则会被截断并平均分配。1. 如果仅提供了一个比率,则另一个颜色会设为 100 减去该比率。

最后一个规则不太明显;如果为两种颜色都提供了百分比,并且它们的总和不等于 100%,会怎么样?

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

这种 color-mix() 组合会产生透明度,40% 透明度。如果这些比率的总和不等于 100%,则生成的混合颜色不会不透明。这两种颜色都不会完全混合。

嵌套 color-mix()

与所有 CSS 一样,嵌套会得到妥善处理并按预期运行;内部函数将先解析,然后将其值返回给父级上下文。

color-mix(in lch, purple 40%, color-mix(plum, white))

您可以根据需要嵌套任意数量的嵌套,以获得所需的结果。

构建浅色和深色配色方案

我们来使用 color-mix() 构建配色方案!

基本配色方案

在以下 CSS 中,系统根据品牌十六进制颜色码创建浅色主题和深色主题。浅色主题会创建两种深蓝色的文本颜色和一个非常浅的白色背景 Surface 颜色。然后,在深色偏好媒体查询中,为自定义属性分配新的颜色,以使背景为深色,文本颜色为浅色。

:root {
  /* a base brand color */
  --brand: #0af;

  /* very dark brand blue */
  --text1: color-mix(in oklab, var(--brand) 25%, black);
  --text2: color-mix(in oklab, var(--brand) 40%, black);

  /* very bright brand white */
  --surface1: color-mix(in oklab, var(--brand) 5%, white);
}

@media (prefers-color-scheme: dark) {
  :root {
    --text1: color-mix(in oklab, var(--brand) 15%, white);
    --text2: color-mix(in oklab, var(--brand) 40%, white);
    --surface1: color-mix(in oklab, var(--brand) 5%, black);
  }
}

所有这些都通过将白色或黑色混入品牌颜色来实现。

中级配色方案

您可以更进一步,添加除浅色和深色主题外的其他主题。在以下演示中,对单选组所做的更改会更新 HTML 标记 [color-scheme="auto"] 上的属性,从而使选择器能够有条件地应用颜色主题。

此中间演示还展示了颜色主题设置方法,其中所有主题颜色都列在 :root 中。这样一来,您就可以轻松查看所有内容,并根据需要进行调整。稍后,您可以在样式表中使用定义的变量。这样可以避免在样式表中搜索颜色操作,因为它们都包含在初始 :root 代码块中。

更多有趣的用例

Ana Tudor 提供了一个非常棒的演示,其中包含一些可供学习的使用场景:

使用开发者工具调试 color-mix()

Chrome 开发者工具对 color-mix() 提供了出色的支持。它会识别并突出显示语法,在“样式”窗格的样式旁边创建混合颜色的预览,并允许选择其他颜色。

它在 DevTools 中应如下所示:

Chrome 开发者工具检查颜色混合语法的屏幕截图。

祝大家混音愉快!