配了三年配色,每次品牌色一换就要回头过一遍文字颜色——今天 CSS 一个函数把这件事彻底原生化了
配了三年配色,每次品牌色一换就要回头把文字颜色全部过一遍——light 主题配深色文字、dark 主题配浅色文字,同样的组件要维护两套规则。今天一个 CSS 函数把这个彻底原生化了。
做设计系统的工程师每天都在处理这个问题:同一个按钮组件,在不同品牌色下文字该显示黑色还是白色?
传统解法:
- 手工维护两套 CSS class
- 用 Sass/Less 写颜色函数计算 luminance
- 用 JS 动态判断背景色亮度再写回去
不管哪种都要写额外代码,而且换主题色的时候要把所有配对关系重新过一遍。
contrast-color() 是什么
Chrome 147+/Firefox 146+/Safari 26+/Edge 147+ 全部支持,2026 年 4 月进入 Baseline,全球约 90% 覆盖率。
css
.button {
background-color: var(–brand-color);
color: contrast-color(var(–brand-color));
}
传什么颜色都行:hex、rgb、hsl、oklch、color-mix() 混色、CSS 变量,浏览器会自动比较这个颜色与黑色的对比度、与白色的对比度,返回得分更高的那个。
WCAG AA 标准(4.5:1)是硬门槛,两个候选都达标的返回对比度更高的那个。如果黑白得分完全相同(比如恰好是中灰色 #808080),返回 white。目前只返回 black 或 white,不支持自定义候选色。
实战场景
品牌色按钮:
css
.button {
–brand: #6b28cc;
background-color: var(–brand);
color: contrast-color(var(–brand));
}
只要改一行 –brand,整套按钮文字颜色就自动适配。
暗色模式无缝切换:
css
body {
–bg: #f5f5f5;
background: var(–bg);
color: contrast-color(var(–bg));
}
@media (prefers-color-scheme: dark) {
body { –bg: #1a1a1a; }
}
亮色背景自动配黑字,暗色背景自动配白字,一个声明搞定。
用户自定义主题:
css
.card {
background-color: var(–user-avatar-color);
color: contrast-color(var(–user-avatar-color));
}
局限(CSS-Tricks 特别指出)
- 只返回黑白,中间色调(比如浅蓝)无论哪个都是弱对比
- 不考虑字号,WCAG 对大字号(18px+ 或 14px bold)要求 3:1,但 contrast-color() 不区分
- 渐变背景不适用,一张渐变背景没法给出一个对比度数字
- 背景图片上的文字无法处理,只能处理纯色
渐进增强写法
css
.status-badge {
–badge: #6b2fb8;
background-color: var(–badge);
color: white; / fallback /
color: contrast-color(var(–badge)); / 现代浏览器覆盖 /
}
结论
contrast-color() 不是万能无障碍药方,但它把设计系统里最常见的「按钮/标签/徽章」类组件的配色问题用一个声明解决了。
下一步:
- 翻一下自己的设计系统,找到这类组件,把手写的黑白配对换成 contrast-color()
- 注意那些用 oklch 或 color-mix 生成的动态色——contrast-color() 对它们同样生效
- 重要文字(正文、说明)不要依赖这个函数,它只管「能看清」,不管「满足 WCAG AA」
评论区
登录后可评论。