改主题色我要调八个地方,现在浏览器自己算——CSS 相对颜色语法实战
做设计系统的时候,最烦的一件事就是:主题色变一个色值,整个组件库要从按钮到标签到图表全改一遍。以前这件事要么靠 Sass 变量层层继承,要么靠 CSS 变量一层层往下传,总有那么几个地方漏掉了。
2026 年,CSS 相对颜色语法终于进了 Baseline Widely Available 状态,这件事变得简单多了。
什么是相对颜色语法
简单说,就是你可以在一个颜色上直接做数学运算,不需要另外声明变量。
/* 以前的写法:先声明一个变量,再一层层继承 */
:root {
--primary: oklch(60% 0.2 240);
--primary-light: oklch(75% 0.15 240); /* 手动调参数 */
--primary-dark: oklch(45% 0.25 240); /* 手动调参数 */
}
/* 相对颜色语法:直接从 --primary 算出来 */
:root {
--primary: oklch(60% 0.2 240);
--primary-light: oklch(from var(--primary) calc(L * 1.2) c h);
--primary-dark: oklch(from var(--primary) calc(L * 0.7) c h);
}
from var(--primary) 的意思是”以 –primary 为基础”,后面的 calc(L * 1.2) c h 是”把它的明度乘以 1.2,色度和色相保持不变”。
就这么一行,不用算具体值,浏览器自己会算。
能做什么
1. 自动变体生成
这是最实用的场景。假设你有一套按钮系统,需要 primary / primary-hover / primary-active 三个状态:
.button {
background: var(--btn-color);
border: 1px solid var(--btn-color);
}
.button:hover {
background: oklch(from var(--btn-color) calc(L * 0.9) c h);
}
.button:active {
background: oklch(from var(--btn-color) calc(L * 0.8) c h);
}
/* 使用的时候 */
.primary { --btn-color: oklch(60% 0.2 240); }
.danger { --btn-color: oklch(60% 0.25 20); }
.warning { --btn-color: oklch(70% 0.2 80); }
一套 CSS 变量搞定所有颜色变体,加新颜色只需要一行。
2. 语义化颜色派生
比如你有一个 surface 背景,需要给上面的文字自动计算一个对比度足够的颜色:
.card {
background: var(--surface);
color: oklch(from var(--surface) calc(L + 0.4) c h);
/* 亮背景上自动得到深色文字 */
}
.dark-card {
--surface: oklch(20% 0.05 240);
/* 深色背景上自动得到浅色文字 */
}
注意这里没有手动算对比度,浏览器按照相对亮度自动调整。
3. 配合 color-mix() 做色调调整
相对颜色语法可以嵌套进 color-mix() 里用:
:root {
--brand: oklch(55% 0.25 260);
/* 把品牌色和白混合,生成浅色版本 */
--brand-tint: color-mix(in oklch, var(--brand) 30%, white);
/* 把品牌色和黑混合,生成深色版本 */
--brand-shade: color-mix(in oklch, var(--brand) 30%, black);
}
兼容性和注意事项
目前 Firefox 126+、Chrome 129+、Safari 17.5+ 均已支持。2026 年已经是 Widely Available 状态,生产可用。
不过有几个细节要注意:
色空间要一致。 from 后面的颜色会被转换到指定的色空间再参与计算。如果你用 oklch 做变体,保持所有颜色都是 oklch 会得到最平滑的结果。
HSL 不推荐做变体。 用 HSL 做相对计算容易出现”色相翻转”的问题(比如说蓝色变暗之后变成了青色),oklch 不会有这个问题。
老项目迁移成本。 如果你项目里大量用了 HEX 或 rgb(),迁移到 oklch + 相对颜色语法收益最大,但改动也最多。建议新组件优先用,存量组件逐步迁移。
下一步怎么走
如果你的项目还没用设计令牌系统,这就是一个很好的起点:
- 把所有颜色改成 oklch
- 用相对颜色语法生成变体系列
- 组件里只引用变量,不写死色值
这样下次换主题色的时候,改一行就够了。
评论区
登录后可评论。