在项目中,颜色有时会失控。我们通常一开始会选择几种精心挑选的品牌颜色,但随着时间的推移,随着项目的发展,我们可能会添加各种颜色。也许我们意识到需要调整按钮颜色的亮度以方便访问,或者我们需要一个略有不同的组件变体。我们如何确保所选颜色符合项目的设计体系?
我一直在探索如何使用相对较新的 CSScolor-mix()
函数来实现这个目的。看到我能生成不同的调色板变化真是太有趣了!让我们深入探讨一下它如何color-mix()
彻底改变你的设计流程。
熟悉该 color-mix() 功能
该color-mix()
函数允许我们指定要混合的两种颜色,然后输出结果。我们可以控制混合中每种颜色的量,以及颜色插值空间,这决定了颜色的混合方式。
颜色插值方法是必需参数。我们将在后面的部分中介绍它。目前,我们将使用它srgb
来演示示例。
我们以百分比形式指定每种颜色的含量。如果我们省略两种颜色的百分比,color-mix()
则默认每种颜色的含量为 50%。如下所示,将red
和blue
等量混合purple
即可得到预期的色调。
.result {
background-color: color-mix(in srgb, blue, red);
}
如果我们只指定一种颜色的百分比,另一种颜色的百分比会自动调整,使总和达到 100%。例如,无论我们指定90%
还是blue
,结果都是一样的——一种以蓝色为主10%
,red
略带红色的颜色。
/* Both these will produce the same resultant color */
color-mix(in srgb, blue 90%, red)
color-mix(in srgb, blue, red 10%)
如果两种颜色的百分比总和小于100%,则color-mix()
操作会略有不同:该总和将保存为 Alpha 乘数,并使用此乘数对两种颜色进行缩放,使其总和达到 100%。(请参阅规范中的“百分比归一化”部分,查看一些示例)。
尽管color-mix()
下面两个函数混合的每种颜色的量相同,但第二个函数(其中百分比之和为40%
)产生相同的颜色,但 alpha 值为0.4
:
/* Result: rgb(128 0 128) */
color-mix(in srgb, blue, red)
/* Result: rgb(128 0 128 / 0.4) */
color-mix(in srgb, blue 20%, red 20%)
创建明暗变化 color-mix()
一个典型的用例是,我们经常需要创建品牌颜色的更浅或更深的变体。为了实现这一点,我们可以将白色或黑色以不同的比例混合到基色中color-mix()
。
下面的示例演示了如何将不同量的white
和black
与基色混合以创建其更亮和更暗的变化,展示了在调整基色强度方面blue
的用途。color-mix()
/* Initial base color */
.bg-blue {
background-color: blue;
}
/* 50% blue, 50% white */
.bg-blue-light {
background-color: color-mix(in srgb, blue, white);
}
/* 25% blue, 75% white */
.bg-blue-lighter {
background-color: color-mix(in srgb, blue, white 75%);
}
/* 50% blue, 50% black */
.bg-blue-dark {
background-color: color-mix(in srgb, blue, black);
}
/* 25% blue, 75% black */
.bg-blue-darker {
background-color: color-mix(in srgb, blue, black 75%);
}
使用自定义属性来重用颜色变化
通过将color-mix()
值存储为自定义属性,我们可以在整个代码中重复使用它们。当我们想要创建品牌主色的更亮或更暗的变体时,这种方法非常有用。
作为示例,下面的代码说明了如何使用--brand
自定义属性创建品牌颜色变化。
:root {
--brand: rgb(0 0 255);
--brand-light: color-mix(in srgb, var(--brand), white);
--brand-lighter: color-mix(in srgb, var(--brand), white 75%);
--brand-dark: color-mix(in srgb, var(--brand), black);
--brand-darker: color-mix(in srgb, var(--brand), black 75%);
}
我们还可以通过混合来创建不同不透明度的变体transparent
:
:root {
--brand: rgb(0 0 255);
--brand-alpha-50: color-mix(in srgb, blue, transparent);
--brand-alpha-75: color-mix(in srgb, blue 75%, transparent);
}
Una Kravets 的文章“使用 color-mix() 创建不透明度变体”对此进行了进一步解释。
示例:使用 color-mix() 自定义属性设置按钮变体的样式
让我们将color-mix()
自定义属性应用到一个实际案例中:为一个简单的按钮设计样式。首先,我们定义主要基色和辅助色的自定义属性。此外,我们还会使用color-mix()
作为辅助色,以便将基色与 混合pink
。
:root {
--brand: rgb(0 0 255);
--brand-light: color-mix(in srgb, blue, white);
--secondary: color-mix(in srgb, var(--brand), pink);
--secondary-light: color-mix(in srgb, var(--secondary), white);
}
接下来,我们将这些颜色应用于主要和次要按钮变体,并使用较浅的颜色变体表示悬停状态。
button {
background-color: var(--brand);
color: white;
}
button:where(:hover, :focus) {
background-color: var(--brand-light);
}
button.secondary {
background-color: var(--secondary);
}
button.secondary:where(:hover, :focus) {
background-color: var(--secondary-light);
}
我们不仅限于在根级别定义自定义属性。例如,我们可以为组件的基色设置自定义属性,并在组件样式中使用 创建此基色的变体color-mix()
。对于次要组件变体,我们可以简单地应用不同的基色。如下所示。
.card {
--color: blue;
background: color-mix(in srgb, var(--color), white 80%);
border-top: 5px solid var(--color);
padding: 1rem;
}
.secondary {
--color: deeppink;
}
这是将此概念应用于各种 UI 组件的演示。
创造温暖和凉爽的变化 color-mix()
虽然创建现有颜色的更亮或更暗的变化是的常见用例color-mix()
,但除此之外,我们还可以通过将暖色或冷色混合到我们的原始调色板中来创建暖色和冷色的变化。
在这里,我们定义了一个初始调色板(从Coolors中获取的颜色),以及我们想要混合的颜色,以使用自定义属性创建暖色和冷色变体。
:root {
--yellow: rgb(221 215 141);
--peach: rgb(220 191 133);
--chocolate: rgb(139 99 92);
--khaki: rgb(96 89 77);
--grey: rgb(147 162 155);
--mix-warm: red;
--mix-cool: blue;
}
.palette > div {
--color: var(--yellow);
&:nth-child(2) {
--color: var(--peach);
}
&:nth-child(3) {
--color: var(--chocolate);
}
&:nth-child(4) {
--color: var(--khaki);
}
&:nth-child(5) {
--color: var(--grey);
}
}
然后,我们使用自定义属性将第二种颜色混合到原始基色中,并指定其数量。我们还指定了默认值,这样,如果没有指定值--mix
,则将使用原始基色。
.palette > div {
background: color-mix(
in srgb,
var(--color),
var(--mix, var(--color)) var(--amount, 10%)
);
}
这样,我们就可以混合不同的颜色并将它们应用到整个调色板。
.cool {
--mix: var(--mix-cool);
}
.cool--20 {
--amount: 20%;
}
.warm {
--mix: var(--mix-warm);
}
.warm--20 {
--amount: 20%;
}
指定插值颜色空间 color-mix()
在前面的部分中,我们使用了srgb
(标准红绿蓝)作为颜色插值方法。我们可以通过修改用于插值的颜色空间来显著改变结果。颜色空间是一个复杂的主题,远远超出了本文的讨论范围,但在决定使用哪种颜色空间时,值得注意一些颜色空间的优缺点color-mix()
。
探索色彩空间选项
颜色插值决定了一种颜色如何过渡到另一种颜色。一个可视化颜色插值的好方法是使用渐变,就像 Adam Argyle 在“颜色插值”部分中所做的那样,其中深入探讨了色彩空间和色域。
传统的 RGB 插值会导致中心插值区域(渐变的中间区域)的颜色变得浑浊,而使用lch
或 时,颜色仍然鲜艳oklch
。如下图所示,当应用于上例中的暖色和冷色调色板时,结果截然不同。
与srgb
和不同hsl
,oklch
和在感知上是一致的。用Lea Verouoklab
的话来说,这意味着:
相同的坐标数值变化产生相同的感知色差
因此,在进行颜色插值时,我倾向于选择oklch
和颜色空间——但选择权在您手中!oklab``color-mix()
了解较短和较长的插值路径
在极坐标(或圆形)颜色空间中,例如oklch
、oklab
和hsl
,我们也可以选择颜色插值的方向。当我们等量混合两种颜色时,最终的色调角将位于两种颜色角度的中间。这将根据插值遵循色环上较短路径还是较长路径而有所不同。
color-mix(in hsl, rgb(255 88 88), rgb(86 86 255));
color-mix(in hsl longer hue, rgb(255 88 88), rgb(86 86 255));
在下面的框架中,通过混合不同颜色空间中的颜色进行实验来观察结果。
浏览器支持 color-mix()
color-mix()
自 2023 年中期起,所有现代浏览器均支持该函数。请记住,并非所有用户都拥有最新的浏览器。确保每个人都能获得良好体验的一种方法是设置初始颜色值。不支持该函数的浏览器color-mix()
将忽略第二个声明。
div {
/* First declaration is fallback for browsers that do not support color-mix() */
background: rgb(150 0 255);
background: color-mix(in srgb, blue, red);
}
或者,我们可以使用功能查询来检测浏览器是否支持color-mix()
并相应地提供样式:
.card {
background: lightblue;
}
@supports (color-mix(in srgb, blue, white)) {
.card {
--color: blue;
background: color-mix(in srgb, var(--color), white 80%);
border-top: 5px solid var(--color);
}
}
如果您使用 PostCSS,则有一个与postcss-preset-env捆绑在一起的PostCSS 插件。此插件允许您编写函数而无需担心浏览器支持,因为您的代码在构建时会自动转换为跨浏览器兼容的 CSS。例如:color-mix()
.some-element {
background-color: color-mix(in srgb, red, blue);
}
变为:
.some-element {
background-color: rgb(128 0 128);
}
值得注意的是,这只适用于静态值,而不适用于 JavaScript 中设置的自定义属性或动态值。
颜色插值资源
如果您有兴趣深入了解网络上的色彩空间和色彩插值,以下几篇文章可以帮助您理解它们:
- 好的,色彩空间作者:Eric Portis
- OKLCH 让浏览器颜色更佳,作者 Jason Lengstorf
- Adam Argyle 的高清 CSS 颜色指南
- 迷恋 Oklch:色彩空间、色域和 CSS 的爱情故事,作者:Geoff Graham
- CSS 中的 LCH 颜色:是什么、为什么以及如何使用?作者:Lea Verou
概括
我们已经了解了如何使用color-mix()
来创建各种颜色,以及如何将该函数与自定义属性结合使用,以便在项目和设计系统中使用。鉴于浏览器支持已经相当完善,我们可以期待 Web 色彩处理的新时代!