
contrast-color() 是 CSS 中一个非常实用的颜色函数。它的基本用法简洁明了:
background: var(--bg-color);
color: contrast-color(var(--bg-color));
当背景色发生变化时,文字颜色会自动在黑色与白色之间切换,省去了手写 JavaScript 判断逻辑的麻烦。然而,问题恰恰出在这里:它默认只会返回黑色 (#000) 或白色 (#fff)。
如果你的设计系统包含了特定的品牌色、主题色,或者你单纯不希望页面呈现出“深底白字 / 浅底黑字”这种标准答案,那么我们就需要更进一步地探索解决方案。
方案一:使用 color-mix() 进行微调
最快捷的思路是,将 contrast-color() 的计算结果作为基础色,再与你的品牌色进行混合。
color: color-mix(
in srgb,
var(--brand-color),
contrast-color(var(--bg-color)) 20%
);
这种方法的优势显而易见:浏览器负责完成“判断背景明暗”的核心工作,而品牌色调的控制权依然掌握在你手中。
混合比例没有绝对标准,但你可以从以下范围开始尝试:
- 浅色背景:混合 10% 到 25% 的品牌色
- 深色背景:混合 30% 到 40% 的品牌色
此方案的优点是接入成本低,易于集成到现有样式中。缺点也同样明显:混合比例需要你手动调试,并且调试后务必验证最终的颜色对比度,否则容易出现“视觉上和谐,但可读性不足”的问题。
方案二:利用 Style Queries 切换调色板
如果你不满足于“在黑白基础上掺入一点颜色”,那么可以尝试另一条路径:使用 Style Queries。
@property --contrast {
syntax: ‘<color>’;
inherits: true;
initial-value: #000;
}
:root {
--bg-color: #f5f5f5;
--contrast: contrast-color(var(--bg-color));
}
@container style(--contrast: #000) {
.card { --text-color: #0066cc; }
}
@container style(--contrast: #fff) {
.card { --text-color: #4da6ff; }
}
这种方式更像是“根据明暗判断结果,切换一整套设计令牌(Design Tokens)”。也就是说,虽然 contrast-color() 返回的仍然是黑或白,但你可以利用这个信号去选择完全不同的文字色、边框色或强调色。
它的优势在于控制粒度更细、更系统化,非常适合构建组件库或设计系统。其现实局限性在于:Firefox 浏览器目前尚未支持 Style Queries。因此,你需要将其视为一种渐进增强方案,而非全平台的兜底方案。
如何选择?
- 如果你只想让文字颜色不那么呆板:优先采用
color-mix() 方案。它改动小,能快速获得收益。
- 如果你在构建一套主题系统,或需要根据背景状态切换整套配色:那么 Style Queries 是更合适的选择。
无论选择哪条路径,有一件事都不可或缺:务必使用真实的最终颜色进行对比度测试。自动化工具可以帮你解决80%的问题,但剩下的20%,尤其是关乎品牌调性与可读性平衡的部分,仍需人工把关。
相关链接:
希望本文的探讨能为你带来启发。如果你在实现过程中有更多心得或疑问,欢迎到 云栈社区 的 CSS 板块与大家一起交流。
|