color-contrast()不能直接当“自动开关”用——仅Chrome 114+、Edge 114+、Safari 16.4+(需手动开启实验特性)支持,Firefox、安卓WebView、微信内置浏览器等主流环境完全不识别,且函数按顺序返回首个达标色而非最优色,必须配合@supports正向检测与外部fallback才能安全落地。

color-contrast() 不能直接当“自动开关”用
它只在 Chrome 114+、Edge 114+ 和 Safari 16.4+(需手动开启实验特性)中可用,Firefox、安卓 WebView、微信内置浏览器、旧版 iOS Safari 等主流环境完全不识别。一旦写进样式但没兜底,文字会静默失效——变成 color: unset,常见表现是黑底黑字或透明不可见。
更关键的是:它不是“智能选最优”,而是“按顺序挑第一个达标”。比如你写 color-contrast(var(--bg) vs #000, #fff, #333 to WCAG21/AA),哪怕 #333 对比度最高,只要 #000 满足 AA,就直接返回 #000,不会继续比较。
@supports 检测必须写对,否则降级失效
错误写法会导致整条规则被丢弃,尤其在安卓 WebView 上:@supports not (color: color-contrast(#000 vs #fff)) 是无效的;@supports (color: color-contrast(#000 vs #fff)) 也会因缺少 to 子句被 Safari/Chrome 拒绝解析。
正确结构只有这一种:
@supports (color: color-contrast(#000 vs #fff to WCAG20/AA)) {
.text-auto {
color: color-contrast(var(--bg-color) vs #000, #fff to WCAG20/AA);
}
}
/* fallback 必须写在 @supports 块外部、上方 */
.text-auto {
color: #000;
}
-
vs前后必须有空格,to后必须跟完整字符串标识符,如WCAG20/AA或WCAG21/AAA - 禁止用
var(--level)替代标准字符串——to var(--level)语法非法 -
var(--bg-color)必须是已计算出的合法颜色值(如#222、rgb(34, 34, 34)),不能是未展开的嵌套变量链
候选色列表不是越多越好,而是越可控越可靠
函数按从左到右顺序逐个比对,遇到第一个满足对比度的就停。这意味着:
- 把
#000放最前,深色背景永远优先选黑,哪怕白字更可读 - 加入中间色(如
#333、#eee)可能让所有候选都不达标,最终回退到第一个——此时函数行为等同于没用 - 真正能落地的组合往往只有两个:明确黑白二选一,例如
#000, #fff或#fff, #000(后者更适合浅色基底)
如果你需要灰阶适配,别指望 color-contrast() 自动插值——它不支持渐变或亮度微调,必须靠 JS 计算 luminance 后动态设色。
和 JS fallback 共存时最容易互相覆盖
常见冲突场景:CSS 里写了 color-contrast() 生效了,但 JS 又执行了 el.style.color = '#fff',结果内联样式优先级更高,CSS 规则被覆盖,文字颜色又变回固定值。
解决思路很实际:
- JS fallback 应只在
@supports不匹配时才注入,避免双重控制 - 给 JS 设置的 color 加
!important并不推荐——改用 class 切换更可控,比如.text-auto--js - 组件库封装时,务必检查是否已有 CSS 变量更新触发了
color-contrast()重算,再重复 JS 计算就是冗余
真正难的不是写对函数,而是让 CSS 原生能力、@supports 降级、JS luminance 判断三者之间不打架——稍不注意,一个页面里就同时存在三种颜色逻辑在抢 control 权。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











