CSS color-mix()

Adam Argyle
Adam Argyle

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

浏览器支持

  • 111
  • 111
  • 113
  • 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() 了解颜色空间的效果对于制作渐变也十分有用。颜色 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 色调通道的任何颜色空间),您可以指定插值是 shorterlongerdecreasing 还是 increasing。如需了解更多信息,本高清色彩指南中对此有详细介绍。

下面是相同的蓝白混合混合示例,但这一次,它只在使用不同色相插值方法的圆柱体空间中。

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

这是我制作的另一个 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 中,浅色和深色主题是基于品牌十六进制颜色码创建的。浅色主题会创建两种深蓝色文本颜色和一种非常浅的白色背景颜色。然后,在深色偏好设置媒体查询中,系统会为自定义属性分配新的颜色,使背景为深色,而文本颜色为浅色。

: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 语法的屏幕截图。

祝大家混音愉快!