CSS color-mix()

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

Browser Support

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

Source

在 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() 工具: - 探索每个色彩空间的效果。 - 探索在圆柱形色彩空间(lch、oklch、hsl 和 hwb)中混合时色调插值的效果。- 点击任意两个顶部颜色框,更改要混合的颜色。- 使用滑块更改混合比例。 - 生成的 color-mix() CSS 代码位于底部。

在各种色彩空间中混合

混合(和 渐变)的默认色彩空间是 oklab。它提供一致的结果。您还可以指定其他色彩空间,以根据需要定制混合。

以 black 和 white 为例。它们混合的色彩空间不会有太大的区别,对吧?错误。

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 种不同的色调,这表明每个色彩空间甚至会以不同的方式混合成灰色。
Try the demo

它确实有很大的影响!

再以 blue 和 white 为例。我特意选择了这个,因为在这种情况下,色彩空间的形状会影响结果。在这种情况下,大多数色彩空间在从白色到蓝色的过程中都会变成紫色。它还展示了 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),每个色彩空间显示的结果都不同。许多是粉色或紫色,很少有实际上仍是蓝色的。
Try the demo

了解 color-mix() 的色彩空间效果对于 制作渐变 也很有用。颜色 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);
}
不同色彩空间中的黑白渐变。
Try the demo

如果您想知道哪个色彩空间是“最好的”,那么没有。这就是为什么有这么多选项!如果有一个是“最好的”,那么也不会有新的色彩空间被发明出来(请参阅 oklch 和 oklab)。 每个色彩空间都有其独特的闪光点,并且是正确的选择。

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

混音结果,如上一段所述。
Try the demo

如果您想要一致性和细微差别,请使用 oklab。在以下混合蓝色和黑色的演示中,hsl 和 hwb 产生了过于鲜艳和色调偏移的颜色,而 srgb 和 oklab 则产生了较深的蓝色。

混音结果,如上一段所述。
Try the demo

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

调整色调插值方法

如果您选择在圆柱形色彩空间中混合,基本上是任何具有接受角度的 h 色调通道的色彩空间 ,您可以指定插值是 shorter、longer、decreasing 还是 increasing。如果您想了解更多信息,请参阅这篇高清颜色指南。

下面是相同的蓝色到白色混合示例,但这次仅在具有不同色调插值方法的圆柱形空间中。

混音结果,如上一段所述。
Try the demo

这是我制作的另一个 Codepen,用于帮助可视化色调插值,但专门用于渐变。我相信,这有助于您了解在指定色调插值时,每个色彩空间如何产生混合结果,请仔细研究一下!

使用不同的颜色语法进行混合

到目前为止,我们主要混合了 CSS 命名颜色,例如 blue 和 white。CSS 颜色混合已准备好混合来自两个不同色彩空间的颜色。这也是指定混合的色彩空间的关键原因,因为它为两个颜色不在同一空间时设置了公共空间。

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

在前面的示例中,hsl 和 display-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 中,根据品牌十六进制颜色码创建了浅色和深色主题。浅色主题创建了两种深蓝色文本颜色和一种非常浅的白色背景表面颜色。然后在深色偏好媒体查询中,自定义属性被分配了新颜色,因此背景为深色,文本颜色为浅色。

: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() 提供了出色的支持。它可以识别并突出显示语法,在“样式”窗格中的样式旁边创建混合的预览,并允许选择替代颜色。

在开发者工具中,它看起来如下所示:

Chrome 开发者工具检查 color-mix 语法。

祝大家混合愉快!