颜色对比实战
达文本 4.5:1、UI 3:1、用工具测试、修常见失败。
无障碍入门
为什么
低对比文本(gray-400 在白)对低视力用户不可见且未过 WCAG 1.4.3。是最常见 a11y 失败且最便宜修 — 从阶选更深明度。
何时使用
每文本/背景配对和每 UI 边界(按钮 vs 背景、图标 vs 背景)查对比。设计时做非后 — Figma 修免费、代码修是 PR。
如何做
1. 目标 — 正常文本 <18px:4.5:1、大文本 ≥18px 或 ≥14px 粗:3:1、UI 组件(图标、边框):3:1、非文本(logo):豁免
2. 工具 — CI 中 axe-core 抓渲染配对;设计中 Polypane/Contrast
3. 加深修 — 文本从 gray-500 到 gray-700,通常阶 +2 步
4. 勿提亮背景 — 提背景达比常破坏设计;改加深文本
5. 暗色模式 — 重查;亮模式过的配对暗模式可能失败(gray-500 在 gray-900)
6. 链接 — 不仅靠色区分(下划线),且链接 vs 正文对比也须过
7. 禁用 — 豁免对比,但确保看起来禁用(opacity 0.5 + cursor not-allowed)
示例
// contrast.ts — 构建时查配对
function ratio(fg: string, bg: string): number {
const l1 = luminance(hexToRgb(fg)), l2 = luminance(hexToRgb(bg));
return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
}
// gray-500 (#6b7280) 在白 = 4.6:1 ✓(临界 — 正文用 gray-600)
// gray-400 (#9ca3af) 在白 = 2.9:1 ✗(未过 4.5:1 — 仅大文本或图标用)
/* 修:加深文本,非提亮背景 */
.muted-bad { color: var(--color-gray-400); } /* 2.9:1 ✗ */
.muted-good { color: var(--color-gray-600); } /* 7.0:1 ✓ */
/* 链接 — 下划线 + 对正文足够对比 */
a { color: var(--color-action-primary); text-decoration: underline; }
/* blue-600 在白 = 4.6:1 ✓ vs gray-900 正文 = 4.5:1 ✓ */
/* 禁用 — 豁免,但视觉禁用 */
button:disabled { opacity: 0.5; cursor: not-allowed; }
常见问题
- ⚠gray-400 弱文本在白 — 2.9:1,未过 4.5:1,最常见 a11y bug
- ⚠链接仅靠色区分 — 色盲用户不知是链接,需下划线
- ⚠亮模式配对暗模式未重查 — 亮过暗失败
最佳实践
- ✓CI 跑 axe-core — 每 PR 自动抓每渲染对比失败
- ✓加深文本修(阶 +2 步),非提背景 — 保设计
- ✓暗模式重查每配对 — 亮 4.6:1 配对暗模式可能降到 3:1