我配颜色配了八年,每次设计师改主色我都要把整张色板重新跑一遍——今天发现浏览器自己会调了,color-mix() 把这件事彻底变了
我配颜色配了八年,每次设计师改主色我都要把整张色板重新跑一遍——今天发现浏览器自己会调了,color-mix() 把这件事彻底变了。
以前怎么做的?要么靠 Sass 的 lighten() / darken(),要么直接给按钮写五套颜色变量。设计师改了主色,变量要改、mixin 要改、有时候连组件里 hardcode 的色值都要改。一套下来十分钟没了,还容易漏。
现在 CSS 自己会算了。
/* 以前:每个状态一个变量,改主色要改五个地方 */
--brand-primary: #3b82f6;
--brand-hover: #2563eb;
--brand-active: #1d4ed8;
--brand-disabled: #93c5fd;
--brand-ghost: rgba(59, 130, 246, 0.1);
/* 现在:只定义主色,剩下的让浏览器自己算 */
--brand: #3b82f6;
--brand-hover: color-mix(in oklch, var(--brand), white 30%);
--brand-active: color-mix(in oklch, var(--brand), white 50%);
--brand-disabled: color-mix(in oklch, var(--brand), white 80%);
--brand-ghost: color-mix(in oklch, var(--brand), transparent 90%);
改一个 --brand,五个派生色全部自动更新。这是 OKLCH 色彩空间的好处——在这个空间里混合颜色,感知上更自然,不会出现 sRGB 里那种”颜色变脏”的问题。
in oklch 和 in srgb 差别有多大?
同一个颜色混合,sRGB 走的是直线,OKLCH 走的是感知均匀路径。看个具体例子:
/* srgb 路径:直接混合,结果可能偏灰偏脏 */
color-mix(in srgb, #3b82f6 50%, white)
/* 实际效果:蓝不蓝白不白,像褪色的衣服 */
/* oklch 路径:感知均匀混合,结果干净 */
color-mix(in oklch, #3b82f6 50%, white)
/* 实际效果:浅蓝,色相保持完好 */
设计系统里做色阶,OKLCH 是首选。sRGB 只适合简单场景。
配合 @function,设计系统直接从三个主色全自动生成
配合前面说过的 @function,可以把色阶生成做成声明式的:
@function tint($color, $amount) {
@return color-mix(in oklch, $color, white calc($amount * 100%));
}
@function shade($color, $amount) {
@return color-mix(in oklch, $color, black calc($amount * 100%));
}
.button {
background: var(--brand);
}
.button:hover {
background: tint(var(--brand), 0.15); /* 15% 白 */
}
.button:active {
background: tint(var(--brand), 0.30); /* 30% 白 */
}
三个函数 + 一个主色,完整设计系统的色阶就出来了。Sass 的 $brand: lighten() 体系可以整个删掉。
暗色模式怎么用 color-mix()
暗色模式下,品牌色要往高了调以保证对比度,用 color-mix() 改一行就行:
@media (prefers-color-scheme: dark) {
/* 白底的主色在黑底下对比度不够,往亮了拉 */
--brand: color-mix(in oklch, #3b82f6, white 20%);
}
不需要重写整套色阶,设计师给的是亮色底的主色,浏览器自己算出来暗色底的版本。
浏览器支持
color-mix() 已经是 Baseline 2023,所有现代浏览器都支持。Safari 16.4+、Chrome 111+、Firefox 113+。相对颜色语法(color-mix(in oklch, var(--brand), white) 这种)同样已支持。
如果项目还要兼容老浏览器,用 @supports 做降级:
.button {
background: var(--brand-fallback); /* 降级色 */
}
@supports (color: color-mix(in oklch, red, blue)) {
.button {
background: color-mix(in oklch, var(--brand), white 30%);
}
}
下一步
设计师给你的色板,第一个色就定义成 CSS 变量,剩下的派生色用 color-mix() 让浏览器算。改主色的时候只需要改一行,全套派生自动更新。
如果团队还在用 Sass 编译颜色,建议把这个流程迁移过去——省掉编译步骤,颜色管理还更灵活。
评论区
登录后可评论。