需自行计算相对亮度后套用公式(L1+0.05)/(L2+0.05)≥4.5判断是否满足WCAG AA标准,其中L1、L2分别为亮色与暗色的归一化gamma反变换后亮度值。

怎么判断两个颜色是否满足 WCAG 对比度要求
浏览器原生不提供对比度计算函数,得自己算。核心是把十六进制或 RGB 颜色转成相对亮度(luminance),再套用公式 (L1 + 0.05) / (L2 + 0.05)(L1 是亮色,L2 是暗色),结果 ≥ 4.5 才满足普通文本的 AA 标准。
-
luminance计算时,每个通道要先归一化,再对 sRGB 值做 gamma 反变换:小于等于 0.03928 的值直接除以 12.92,否则用((val + 0.055) / 1.055) ** 2.4 - 别直接用
getComputedStyle(el).color返回的 rgb() 字符串去正则提取——IE 返回的是rgb(100,100,100),Chrome 可能返回rgb(100 100 100)(空格分隔),新版还可能带 alpha;建议用window.getComputedStyle+new Option().style.color = color; getComputedStyle(new Option()).color统一转成 rgb() 再解析,或直接用库如tinycolor2 - 深灰文字(
#333)配浅灰背景(#eee)看似有层次,但实际对比度只有 ~2.1,不达标;别依赖肉眼判断
HTML 中哪些地方必须检查颜色对比
不是所有文本都需要 4.5:1,但以下节点一旦用了非默认颜色,就得验证:
- 所有
<p>、<span>、<label>等承载用户可读文本的元素,只要设置了color或background-color -
<button>和<a>的默认样式被覆盖后——尤其禁用态(:disabled)常被设成#aaaon#f5f5f5,对比度常跌破 3:1 - 伪元素内容(
::before/::after)如果含文本(比如用content: "必填"),也计入可读文本范围,但很多检测工具会漏掉 - SVG 内的
<text>元素同样适用 WCAG,但fill和stroke都要分别验;纯装饰性 SVG 可加aria-hidden="true"排除
用 JavaScript 实时检测页面颜色对比的最小可行方案
不需要引入整套 axe-core,几行代码就能抓出高风险节点:
function checkContrast(el) {
const style = getComputedStyle(el);
const fg = parseColor(style.color);
const bg = parseColor(style.backgroundColor);
return getContrastRatio(fg, bg) < 4.5;
}
document.querySelectorAll('p, span, label, button, a').forEach(el => {
if (checkContrast(el)) console.warn('低对比度:', el);
});-
parseColor必须处理currentcolor、transparent、hsl()、named colors(如darkblue)等,推荐复用tinycolor2的new tinycolor(color).toRgb() - 别只查
color和background-color——如果父级有opacity: 0.9,子元素实际对比度会下降,但 CSS 不会透传 opacity 到子元素 computedStyle,得递归向上合成透明度 - 运行时机很重要:要在所有样式加载完毕后执行(比如
DOMContentLoaded后延时 100ms),否则getComputedStyle可能取到未生效的初始值
为什么 inline-style 里写死 #000 on #fff 还可能失败
看起来最安全的颜色组合,也可能在特定上下文中失效:
立即学习“前端免费学习笔记(深入)”;
- 用户开启了系统级“高对比度模式”(Windows / macOS),浏览器会强制替换页面颜色,
color可能被覆盖为系统主题色,此时你写的#000无效 - CSS 自定义属性(
--text-color)若在 :root 外被重定义,且没设 fallback,color: var(--text-color, #000)在旧浏览器里会退化为color: #000,但若变量本身是inherit,最终结果就不可控 - 字体渲染差异:Mac 上 subpixel antialiasing 会让浅灰文字边缘发虚,实际感知对比度比理论值低 10–15%,尤其小字号(
12px)下更明显
真正难的不是算数字,而是确认那个数字对应的是用户此刻真实看到的像素——CSS 层叠、系统设置、字体引擎、甚至显示器 ICC 配置,都在悄悄改写你的对比度。











