⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

3.8.3 颜色对比度

一句话破题

足够的对比度让所有人都能看清你的内容,包括在阳光下看手机的普通用户。

核心价值

低对比度的文字让视力正常的人在光线不好时也难以阅读。WCAG 规定了最低对比度要求,满足它对所有用户都有益。

WCAG 对比度要求

级别普通文字大字/粗体说明
AA4.5:13:1最低要求
AAA7:14.5:1更高标准

大字定义:18pt (24px) 以上,或 14pt (18.5px) 加粗

对比度计算工具

tsx
// 对比度计算函数
function getLuminance(r: number, g: number, b: number): number {
  const [rs, gs, bs] = [r, g, b].map((c) => {
    c = c / 255
    return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)
  })
  return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs
}

function getContrastRatio(color1: string, color2: string): number {
  const rgb1 = hexToRgb(color1)
  const rgb2 = hexToRgb(color2)
  
  const l1 = getLuminance(rgb1.r, rgb1.g, rgb1.b)
  const l2 = getLuminance(rgb2.r, rgb2.g, rgb2.b)
  
  const lighter = Math.max(l1, l2)
  const darker = Math.min(l1, l2)
  
  return (lighter + 0.05) / (darker + 0.05)
}

function hexToRgb(hex: string) {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16),
  } : { r: 0, g: 0, b: 0 }
}

// 使用
const ratio = getContrastRatio('#3B82F6', '#FFFFFF')
console.log(`对比度: ${ratio.toFixed(2)}:1`) // 4.51:1

常见问题配色

问题差的配色好的配色
灰色文字#999 on #fff (2.85:1)#666 on #fff (5.74:1)
蓝色链接#60A5FA on #fff (2.77:1)#2563EB on #fff (4.88:1)
成功色#22C55E on #fff (2.43:1)#15803D on #fff (4.96:1)

安全配色方案

css
:root {
  /* 确保满足 AA 标准的配色 */
  
  /* 文字颜色 */
  --text-primary: #111827;     /* on white: 16.02:1 */
  --text-secondary: #4B5563;   /* on white: 7.50:1 */
  --text-muted: #6B7280;       /* on white: 5.24:1 */
  
  /* 按钮颜色 */
  --btn-primary: #2563EB;      /* white text: 4.88:1 */
  --btn-success: #15803D;      /* white text: 4.96:1 */
  --btn-danger: #DC2626;       /* white text: 4.51:1 */
  
  /* 链接 */
  --link-color: #1D4ED8;       /* on white: 6.95:1 */
}

不只依赖颜色

色盲用户可能无法区分红/绿,所以不要只用颜色传达信息:

tsx
// 差:只用颜色区分状态
<span className="text-green-500">成功</span>
<span className="text-red-500">失败</span>

// 好:颜色 + 图标
<span className="text-green-600 flex items-center">
  <CheckIcon className="w-4 h-4 mr-1" />
  成功
</span>
<span className="text-red-600 flex items-center">
  <XIcon className="w-4 h-4 mr-1" />
  失败
</span>

// 表单错误:颜色 + 图标 + 位置
<div>
  <input 
    className={cn(
      "border rounded",
      error ? "border-red-500" : "border-gray-300"
    )}
    aria-invalid={!!error}
    aria-describedby={error ? "email-error" : undefined}
  />
  {error && (
    <p id="email-error" className="text-red-600 text-sm mt-1 flex items-center">
      <AlertCircle className="w-4 h-4 mr-1" />
      {error}
    </p>
  )}
</div>

图表可访问性

tsx
// 差:只用颜色区分数据系列
<LineChart data={data}>
  <Line stroke="#3B82F6" />
  <Line stroke="#10B981" />
  <Line stroke="#F59E0B" />
</LineChart>

// 好:颜色 + 形状/线型
<LineChart data={data}>
  <Line 
    stroke="#3B82F6" 
    strokeDasharray="none"
    dot={{ shape: 'circle' }}
  />
  <Line 
    stroke="#10B981" 
    strokeDasharray="5 5"
    dot={{ shape: 'square' }}
  />
  <Line 
    stroke="#F59E0B" 
    strokeDasharray="10 3"
    dot={{ shape: 'triangle' }}
  />
  <Legend />
</LineChart>

焦点状态对比度

css
/* 焦点轮廓需要足够对比度 */
:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: 2px;
}

/* 在深色背景上 */
.dark :focus-visible {
  outline: 2px solid #60A5FA;
}

/* 高对比度模式 */
@media (prefers-contrast: high) {
  :focus-visible {
    outline: 3px solid currentColor;
  }
}

检测工具使用

tsx
// Chrome DevTools 检测
// 1. 打开 DevTools
// 2. Elements 面板选择元素
// 3. Styles 面板点击颜色值
// 4. 查看 Contrast ratio

// Lighthouse 审计
// 1. DevTools > Lighthouse
// 2. 勾选 Accessibility
// 3. 运行审计

// axe DevTools
// 1. 安装 axe DevTools 扩展
// 2. DevTools > axe DevTools
// 3. 扫描页面

暗色模式对比度

css
/* 暗色模式同样需要满足对比度要求 */
[data-theme="dark"] {
  --background: #111827;
  --foreground: #F9FAFB;        /* on dark: 15.37:1 */
  --muted: #9CA3AF;             /* on dark: 7.35:1 */
  
  /* 避免纯黑背景 + 纯白文字(对比度太高也不舒服) */
  /* 避免深灰背景 + 浅灰文字(对比度不足) */
}

AI 协作指南

核心意图:让 AI 帮你检查和优化颜色对比度。

需求定义公式

  • 检查内容:[配色方案/特定组件]
  • 目标级别:WCAG [AA/AAA]
  • 背景颜色:[亮色/暗色/都要]

示例 Prompt

请检查我的配色方案是否满足 WCAG AA 标准:
背景: #FFFFFF
主要文字: #374151
次要文字: #9CA3AF
链接: #3B82F6
按钮: #2563EB (白色文字)
如果不满足,请提供替代颜色

验收清单

  • [ ] 文字对比度达到 4.5:1 (AA)
  • [ ] 大字对比度达到 3:1
  • [ ] 不只依赖颜色传达信息
  • [ ] 焦点状态清晰可见
  • [ ] 暗色模式对比度达标