WCAG 2.1 要求正常文本对比度≥4.5:1,需用相对亮度公式(L1+0.05)/(L2+0.05)计算,不可凭经验判断;例如#ffffff配#333333为4.48:1不达标,而#212529为4.67:1达标。

对比度公式必须用 WCAG 2.1 的 4.5:1 标准
浅色背景(比如 #ffffff、#f8f9fa)下文字是否可读,不能靠“看着还行”判断。WCAG 2.1 明确要求正常文本(小于 18pt 或 14pt 加粗)的对比度至少为 4.5:1。这个比值不是简单算 RGB 差值,而是基于相对亮度和对比度函数:先算两个颜色的 L1 和 L2(归一化后的相对亮度),再代入公式 (L1 + 0.05) / (L2 + 0.05)(亮色为 L1,暗色为 L2)。浏览器 DevTools 的无障碍面板会自动计算,但手动验证时得用这个公式——否则用错公式(比如只看灰度差)会导致误判。
常见浅色背景对应的安全文字色速查
不是所有深灰都达标。例如在 #ffffff 上,#333333 对比度是 4.48:1,**不达标**;而 #212529(Bootstrap 默认 body 文字色)是 4.67:1,刚好过线。其他典型组合:
-
#f8f9fa背景 → 至少用#212529(4.52:1),不用#343a40(4.49:1) -
#e9ecef背景 → 必须用#212529(4.51:1),#343a40只有4.28:1 -
#dee2e6背景 → 即使#212529也仅4.33:1,得换更黑的,如#1a1e23(4.53:1)
用 JavaScript 实时验算对比度(避免手动查表)
开发中常需动态检查配色,直接调用浏览器原生 API 最稳:window.getComputedStyle 拿到颜色后,用 getContrastRatio(部分浏览器支持)或自己实现 WCAG 公式。更通用的做法是复用成熟库逻辑,比如 color-contrast npm 包,或抄一段轻量函数:
function getLuminance(hex) {
const rgb = /^#([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i.exec(hex);
const r = parseInt(rgb[1], 16) / 255;
const g = parseInt(rgb[2], 16) / 255;
const b = parseInt(rgb[3], 16) / 255;
const a = [r, g, b].map(v => v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4));
return 0.2126 * a[0] + 0.7152 * a[1] + 0.0722 * a[2];
}
function getContrastRatio(color1, color2) {
const l1 = getLuminance(color1);
const l2 = getLuminance(color2);
return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
}
// 示例:getContrastRatio('#ffffff', '#212529') → ~4.67
立即学习“前端免费学习笔记(深入)”;
灰色系文字在浅背景上最容易翻车
设计师偏爱浅灰文字(如 #6c757d)营造“柔和感”,但它在 #ffffff 上对比度只有 2.9:1,连 AA 级最低要求都不到。更隐蔽的问题是:同一段 CSS 里 color: #495057 在 #f8f9fa 上勉强达标(4.52:1),但若背景被覆盖成 #e9ecef(比如悬停态或主题切换),立刻掉到 4.28:1 —— 这种上下文依赖的失效,往往要等做无障碍审计时才暴露。所以别迷信固定色值,优先用 CSS 自定义属性配合 @media (prefers-contrast: high) 做兜底。










