想象一个雨夜,你走到一座陌生城市的十字路口。路灯昏黄,斑马线的白漆被岁月磨得发白,红绿灯在雨幕里晕成一团光晕。路口对面,老爷爷举着手机凑到眼前看导航,一位色盲小哥在红绿灯前犹豫不决,推婴儿车的妈妈身后还跟着刚下飞机、看不懂本地路牌的外国游客。这个路口并不特殊——每一个 AI 产品界面,都是这样一座十字路口。色彩对比度,就是路口的「路灯与白漆」:文字与背景之间的亮度差,决定了信息能否被行人看清。本文用整套「路口」的比喻,带你学会对比度怎么算、色盲用户如何被照顾、低视力用户如何放大文字、跨国用户如何不被颜色误导,以及 AI 如何让路口学会自动调光。读完你会得到一把「视力标尺」,从此做出的界面,就像一座设计精良的十字路口——老爷爷、色盲小哥、外国游客,都能稳稳走过。

岗位关联

无障碍不是加分项,而是基本功。掌握这套对比度与视觉无障碍方法,你能让 AI 产品对全球超 10 亿视障与老年用户无门槛可用,规避法律风险、扩大市场边界,成为团队里不可替代的「包容性设计专家」。

目录
  1. 可视化演示
  2. 对比度基础
  3. 色盲色弱适配
  4. 低视力支持
  5. 非文本对比
  6. 国际化色彩
  7. 设计实践规范
  8. AI时代无障碍
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

动态演示无障碍设计的核心机制,通过总览/传输/转换/输出四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

无障碍设计:色彩对比 色彩对比度无障碍核心原则 对比度标准与等级划分 核心机制可视化 无障碍设计整体架构与关键组件

对比度基础

深夜走过一条修了十年的老街,你一定能体会到「路灯不够亮」的恐惧:路面灰蒙蒙一片,脚下的井盖、台阶的边缘全都隐没在黑暗里。可一旦路灯齐刷刷亮起来,路面的白线、砖缝立刻有了层次。界面里的色彩对比度,就是这排路灯——它衡量的是文字与背景之间「亮度差」到底有多大。差得越大,信息越显眼;差得越小,就像一盏坏掉的路灯,信息被黑暗吞没。WCAG(Web 内容无障碍指南)正是用一串严谨的数学公式来给这排路灯定标准。

要让路灯「亮得科学」,首先要理解人眼如何感知颜色。我们看到的每种颜色,都可以换算成一个 0 到 1 之间的「相对亮度」数值——0 是纯黑,1 是纯白,0.5 是中等灰。计算时,需要先把 sRGB 颜色值做「线性化」处理,再按人眼对三原色的敏感度加权:

有了相对亮度,就可以计算两个颜色之间的对比度了。WCAG 用「亮者加 0.05」除以「暗者加 0.05」来定义对比度比值,0.05 模拟的是屏幕反光和周边环境光对纯黑的抬升:

路口的白漆不会永远雪白,界面配色也会因为品牌主色、渐变、透明度而「褪色」。把对比度公式写进设计流程,就像给路灯装了定时巡检——每天亮灯前测一次亮度,这条路上的行人就永远不会在黑暗里摸索。这,就是一切视觉无障碍的起点。

L=0.2126×Rlin+0.7152×Glin+0.0722×Blin\displaystyle L = 0.2126 \times R_{lin} + 0.7152 \times G_{lin} + 0.0722 \times B_{lin}
人眼对绿色最敏感,所以绿色通道的权重高达 0.7152;蓝色最不敏感,权重只有 0.0722。这就是为什么同一亮度的红蓝两色,观感亮度完全不同。
C=L1+0.05L2+0.05\displaystyle C = \frac{L_1 + 0.05}{L_2 + 0.05}
对比度 1:1 表示两个颜色完全一样,21:1 是理论极限(纯黑对纯白)。WCAG 规定:普通正文至少 4.5:1,大字号(18pt/14pt 加粗以上)可放宽到 3:1,AAA 级则要求 7:1。
  1. 分子取较亮色两个颜色中相对亮度较大的那个放在分子,保证对比度永远大于等于 1。
    L1=max⁡(LA,LB)\displaystyle L_1 = \max(L_A, L_B)
  2. 分母取较暗色较暗的亮度放在分母。亮度差越大,比值越大,可读性越强。
    L2=min⁡(LA,LB)\displaystyle L_2 = \min(L_A, L_B)
  3. 环境光修正分子分母各加 0.05,模拟纯黑屏幕也会被环境光微微抬亮,避免除以零。
    C=L1+0.05L2+0.05\displaystyle C = \frac{L_1 + 0.05}{L_2 + 0.05}
  4. 阈值判定把算出的 C 与目标级别比较——普通文本 AA 要求 4.5:1,大字与 UI 组件要求 3:1,AAA 要求 7:1。
    C≥4.5⇒普通文本 AA 达标\displaystyle C \geq 4.5 \Rightarrow \text{普通文本 AA 达标}

色盲色弱适配

假设你是个红绿色盲者,站在一个只有红绿两种信号灯的路口:左看右看,两种灯都是一种灰黄色,只能靠「上方还是下方」来猜。这个场景在世界各地每天发生——全球约 8% 的男性和 0.5% 的女性有某种色觉障碍。他们不是看不见颜色,而是某些颜色对(红/绿、蓝/黄)在他们眼中被压缩成了同一个色相。AI 产品里,如果只靠「红色=错误、绿色=成功」来传递状态,这些用户就会迷失在路口中央。

解决办法听起来很简单:给信息穿上第二件衣服。一个状态不仅要有颜色,还要有形状、文字或图案——就像优秀的路口不仅有红绿灯,还有箭头指示灯、斑马线和盲道砖。用「颜色 + 形状」双通道编码,即使颜色通道完全失效,形状通道依然能把用户安全送达。设计图表时,错误数据线用「红色实线」不如「红色虚线」稳健——因为虚线与实线的形状差异,在色盲模拟下依然清晰可辨:

斑马线为什么能成为世界通用的安全标识?因为它不依赖颜色——黑白条纹的亮度对比在任何色觉下都成立。你的 AI 产品里,红色报错、绿色成功、蓝色链接,都应该配上「图标 + 文字」这对永不褪色的条纹,让每个色觉世界的用户都看懂路口的信号。

Csim=Lsim(A)+0.05Lsim(B)+0.05≥3:1\displaystyle C_{sim} = \frac{L_{sim}(A) + 0.05}{L_{sim}(B) + 0.05} \geq 3 : 1
这里的 L_sim 表示把颜色经过色盲模拟矩阵映射之后的相对亮度。也就是说:不是检查「正常人看到的对比度」,而是检查「红绿色盲用户看到的对比度」。
  1. 模拟视界把颜色通过色盲模拟矩阵映射,模拟缺失某类感光细胞后的视觉世界。
    (R′,G′,B′)=Mdeuteranopia×(R,G,B)\displaystyle (R', G', B') = M_{deuteranopia} \times (R, G, B)
  2. 重算亮度在模拟后的颜色上重新计算相对亮度 L_sim,取代原亮度。
    Lsim=0.2126Rlin′+0.7152Glin′+0.0722Blin′\displaystyle L_{sim} = 0.2126 R'_{lin} + 0.7152 G'_{lin} + 0.0722 B'_{lin}
  3. 对比阈值模拟后对比度仍须达到 3:1,确保状态信息在色盲视界中不丢失。
    Lsim(A)+0.05Lsim(B)+0.05≥3\displaystyle \frac{L_{sim}(A) + 0.05}{L_{sim}(B) + 0.05} \geq 3
  4. 双通道兜底即使达到 3:1,也必须叠加文字/图标/图案等第二个信息通道。
    通道数(颜色,形状,文字)≥2\displaystyle \text{通道数}(颜色, 形状, 文字) \geq 2

低视力支持

老花镜、放大镜、手机字号调到「超大」——这是许多长辈与视力障碍者每天的生活状态。低视力不等于全盲,而是「标准尺寸看不清、标准对比度看不见」。白内障让世界蒙上一层雾,黄斑变性让视野中央出现黑洞,青光眼让余光一点点消失。据统计,60 岁以上人群中超过三分之一有不同程度的视力损伤。AI 产品如果只按设计师 20/20 的视力来设计,就等于把路灯挂到 10 米高——年轻人能看清,长辈们只能靠感觉摸黑前行。

低视力支持的核心不是「把字变大」这一个动作,而是「允许用户自己把字变大」的弹性机制。WCAG 1.4.4 要求文本可缩放至 200% 而不丢失内容;不仅是字号,行高、段距、点击目标也要跟着可缩放体系走。Windows 的高对比度模式、iOS 的「增强对比度」开关,都是系统层面的第二排路灯。设计时用相对单位(rem),让界面像橡皮筋一样随用户设置伸缩:

给路口安装可调节的路灯杆,让行人自己决定灯光高度——这就是低视力支持的设计哲学。你不必猜测每个用户的老花度数,只需把「调节权」交还用户,并保证调节后的一切信息依然完整、可读、可点。AI 产品常说「千人千面」,视觉上也该有「千人千灯」。

Sview=Sdesign×zzoom,zzoom≥2.0\displaystyle S_{view} = S_{design} \times z_{zoom}, \quad z_{zoom} \geq 2.0
S_view 是用户最终看到的视觉尺寸,S_design 是设计师定的基准字号,z_zoom 是用户/系统的缩放倍率。要求是:放大到 2 倍后,内容不截断、不重叠、不丢失。
  1. 基准字号S_design 是设计稿中的基准大小,建议正文不低于 16px,避免小字号放大后的锯齿。
    Sdesign≥16px\displaystyle S_{design} \geq 16\text{px}
  2. 用户缩放z_zoom 由浏览器设置、系统辅助功能或用户手势决定,必须允许至少 2 倍。
    zzoom∈[1.0,2.0+], 连续可调\displaystyle z_{zoom} \in [1.0, 2.0+], \text{ 连续可调}
  3. 布局弹性放大后容器用弹性布局,文字可换行、组件可伸展,不得溢出裁剪。
    htext≤hcontainer,∀zzoom≤2.0\displaystyle h_{text} \leq h_{container}, \forall z_{zoom} \leq 2.0
  4. 目标尺寸视觉尺寸之外,点击目标(按钮、链接)至少 44×44 CSS 像素,方便抖动的手精准命中。
    wtarget×htarget≥44×44px\displaystyle w_{target} \times h_{target} \geq 44 \times 44\text{px}

非文本对比

路口的安全不只是信号灯的事——斑马线边缘的白线、路缘石的黄黑警示条、地面井盖的凹凸,都在无声地引导行人。界面同理:文字有对比度要求,按钮边框、图标、输入框底线、键盘焦点框这些「非文本元素」同样需要清晰的视觉边界。WCAG 1.4.11 明确要求:UI 组件的视觉边界、图形对象(如图标)与相邻颜色之间的对比度,至少达到 3:1。

这条规定救了很多「若隐若现」的界面。你见过那些只有一条极淡灰色底线的输入框吗?在阳光直射的屏幕上几乎消失;你点过那种靠颜色深浅区分选中/未选中的标签页吗?焦点在哪里全靠猜。把非文本对比度纳入检查,就像把路缘石刷上黄黑条纹——即使灯光昏暗,行人也能凭边界感安全行走。图标与背景的对比度可以这样验证:

一个完美无障碍的路口,即使闭上一只眼、摘下眼镜,也能凭边界、反光条和路缘石走完全程。界面中的「路缘石」就是这些不起眼的边框与焦点环。把非文本对比度写进设计系统,等于承诺:一切可交互之物,必然可见。

Cui=Lcomponent+0.05Lbackground+0.05≥3:1\displaystyle C_{ui} = \frac{L_{component} + 0.05}{L_{background} + 0.05} \geq 3 : 1
组件/图标/焦点环的亮度与背景亮度之比达到 3:1,保证用户能在 1.5 米外(即一臂距离看手机)清晰分辨「哪里有可交互的东西」。
  1. 组件亮度取按钮边框、图标线条或焦点指示环的颜色,计算相对亮度。
    Lcomponent=相对亮度(组件颜色)\displaystyle L_{component} = \text{相对亮度}(组件颜色)
  2. 背景亮度取组件所处背景的颜色亮度,两者是直接的「图与底」关系。
    Lbackground=相对亮度(背景颜色)\displaystyle L_{background} = \text{相对亮度}(背景颜色)
  3. 比值计算沿用对比度公式,亮者在上、暗者在下。
    Cui=max⁡(Lc,Lb)+0.05min⁡(Lc,Lb)+0.05\displaystyle C_{ui} = \frac{\max(L_c, L_b) + 0.05}{\min(L_c, L_b) + 0.05}
  4. 阈值 31:组件级要求低于正文的 4.5:1,但高于「可感知」的最低线,并需在整页范围内保持一致。
    Cui≥3\displaystyle C_{ui} \geq 3

国际化色彩

同一个路口,到了不同国家规则大变:英国靠左行驶,中国靠右行驶;红灯在很多国家代表「停」,在金融语境里却可能代表「涨」。颜色是最容易被忽略的「文化暗号」——中国股市红色代表上涨、绿色代表下跌,而美股恰好相反。如果你的 AI 产品同时服务中美用户,K 线图的红绿直接颠倒,用户轻则困惑,重则误判交易。紫色在泰国是丧服色,白色在中国传统中也是丧事用色,但在西方婚礼上象征纯洁——AI 出海时,每一次配色都可能在某个文化里「说错话」。

国际化色彩的第一原则:颜色永远不能是唯一的信息载体。正如国际路标用红圈表示禁止、三角形表示警告,它们不依赖文字也能被各国司机理解——因为你既看颜色,也看形状。金融涨跌可同时用「颜色 + 向上/向下箭头」,状态提示用「色块 + 图标 + 文案」。第二原则是用本地化测试验证颜色语义的理解率:

「禁止通行」的牌子只要画上红圈白杠,全世界都不需要认识字。AI 产品走向全球时,你的配色方案也该像国际路标一样「自解释」——用形状和文字把颜色的语义再讲一遍。这不是对设计的束缚,而是让产品在 200 个国家的文化里都不迷路的导航系统。

Pok=NokNtotal≥0.9\displaystyle P_{ok} = \frac{N_{ok}}{N_{total}} \geq 0.9
P_ok 是目标文化用户中正确理解该颜色语义的人群比例。低于 90% 就说明这个颜色「出了国就变味」,必须替换成更安全的表达方式。
  1. 样本测试在目标市场招募代表用户,展示颜色 UI,询问他们感知到的含义。
    Ntotal=受访总人数,Nok=理解正确人数\displaystyle N_{total} = \text{受访总人数}, \quad N_{ok} = \text{理解正确人数}
  2. 通过率计算正确理解的人数占比即为该颜色语义在文化中的「识字率」。
    Pok=NokNtotal\displaystyle P_{ok} = \frac{N_{ok}}{N_{total}}
  3. 阈值 0.990% 是经验安全线;金融、医疗等高风险场景建议趋近 100%。
    Pok≥0.9\displaystyle P_{ok} \geq 0.9
  4. 双通道兜底无论 P_ok 多高,颜色之外必须存在文字/图标通道,彻底消除歧义。
    信息语义=颜色⊕形状/文字\displaystyle \text{信息语义} = \text{颜色} \oplus \text{形状/文字}

设计实践规范

再好的路口设计,如果没人定期刷漆、维修路灯、清理遮挡视线的树枝,三年后也会变得危机四伏。无障碍设计最大的敌人不是无知,而是「褪色」——团队换人、组件迭代、紧急上线,对比度悄悄跌破 4.5:1 而无人察觉。因此,成熟团队会把对比度检查做成「城市道路巡检制度」,而不是一次性的装修工程。

设计实践规范的第一件事,是把对比度安全色写进设计系统。设计系统里的每个颜色 token 都标注它的「安全使用场景」:哪些颜色可作正文、哪些只能做装饰、哪些必须搭配特定背景。第二件事是自动化检查:将 Axe、Lighthouse、Stark 等工具接入 CI/CD 流水线,每次代码提交自动扫描页面,对比度违规直接阻断发布。第三件事是建立覆盖率指标——每一类组件都要有对应的无障检测用例:

路口每年都有巡检表,每个组件也应该有一张「无障检查卡」。把覆盖率指标写进团队的定义完成(DoD),让「对比度合格」成为上线的必达条件——就像路灯不亮的路口不得通车一样。长期坚持,无障碍会从「补救动作」变成「肌肉记忆」。

Coverage=NpassNtotal×100%≥95%\displaystyle Coverage = \frac{N_{pass}}{N_{total}} \times 100\% \geq 95\%
覆盖率 = 通过自动化对比度检查的组件数 ÷ 团队组件库中全部组件数。95% 是及格线,剩余 5% 留给需要人工判断的复杂图形。
  1. 组件清单先盘点产品里所有可交互与信息展示组件,得到总数 N_total。
    Ntotal=∑i=1k组件类型i\displaystyle N_{total} = \sum_{i=1}^{k} \text{组件类型}_i
  2. 自动扫描用无障检查工具逐个组件计算对比度,记录通过数 N_pass。
    Npass=∑[Ci≥阈值i]\displaystyle N_{pass} = \sum \left[ C_i \geq \text{阈值}_i \right]
  3. 覆盖率计算通过数除以总数,得到检查覆盖率。
    Coverage=NpassNtotal×100%\displaystyle Coverage = \frac{N_{pass}}{N_{total}} \times 100\%
  4. 验收标准覆盖率 ≥ 95%,且不允许存在阻断级(对比度严重不足)问题遗留。
    Coverage≥95%∧Nblocker=0\displaystyle Coverage \geq 95\% \wedge N_{blocker} = 0

AI时代无障碍

未来的十字路口会是什么样?传感器感知到天色渐暗,自动调亮路灯;识别到前方有视力障碍的行人,交通灯会发出声音提示、放大倒计时数字;系统甚至能根据行人的步速,动态调整绿灯时长。这就是 AI 时代无障碍的图景——不再是「修一条标准的路」,而是「让路主动适应每一个人」。AI 产品正在把这种智能带入界面设计。

AI 在视觉无障碍中最成熟的应用是自动检测:计算机视觉模型扫描页面截图,用图像分割定位文本区域与背景,自动计算对比度并标注违规位置,甚至可以生成「替代色方案」。设计师在 Figma 里画完一屏界面,AI 插件三秒内给出无障报告,比人工检查快十倍。个性化适配则是另一条路线:系统读取用户的视觉档案(年龄、视力状况、环境光照),动态调整目标对比度,而不是一刀切地套用固定阈值:

与此同时,全球监管正在加速:欧洲无障碍法案(EAA)2025 年强制生效,美国 ADA 诉讼逐年攀升,中国《无障碍环境建设法》2023 年已施行——AI 生成界面必须把合规内置在生成逻辑里,而不是事后补救。智能路口不是把路修得更宽,而是把信号调得让每个人都能读懂;AI 时代的无障碍,正是让每一条斑马线学会「看见」每一位行人。

Ctarget=max⁡(CAA,  f(环境光,用户视力))\displaystyle C_{target} = \max\left(C_{AA}, \; f(环境光, 用户视力)\right)
C_target 是系统为该用户动态计算的目标对比度。它至少不低于 WCAG 的 AA 标准,同时根据环境光强度和用户视力状况上调——环境越暗、视力越弱,目标越高。
  1. 标准底线无论个性化程度多高,都不能低于 WCAG AA 的硬性标准。
    CAA=4.5:1 (普通文本)\displaystyle C_{AA} = 4.5 : 1 \ (\text{普通文本})
  2. 环境映射函数 f 把环境光强度 E 与用户视力敏锐度 V 映射为附加对比度需求。
    f(E,V)=α⋅(1−E)+β⋅(1−V),α,β>0\displaystyle f(E, V) = \alpha \cdot (1 - E) + \beta \cdot (1 - V), \quad \alpha, \beta > 0
  3. 取最大值个性化需求与法定标准取较大者,保证「只高不低」。
    Ctarget=max⁡(CAA,f(E,V))\displaystyle C_{target} = \max(C_{AA}, f(E, V))
  4. 闭环校准页面实际渲染对比度必须大于等于目标值,AI 持续监测并自动校准。
    Cdisplay≥Ctarget⇒合规\displaystyle C_{display} \geq C_{target} \Rightarrow \text{合规}

AI 应用场景

场景一:AI 实时无障审稿插件

阶段:AI 辅助设计(生成与校验)

解决的问题:设计师在 Figma 中大量使用柔和色、渐变与透明度,传统人工检查要到开发完成后才能发现对比度问题,返工成本极高。AI 插件在画布上实时扫描每个图层对(文字与背景、组件与相邻元素),自动计算 WCAG 对比度并标注违规区域,同时推荐达标替代色。

具体案例:某 AI 医疗产品团队的界面里,「删除患者数据」按钮使用浅灰底+白字,对比度仅 2.1:1。AI 插件在设计师绘制的瞬间弹出警示,并推荐「深红底 #F43F5E + 白字」方案,对比度提升到 5.2:1。设计师一次到位,省去开发返工。

场景二:国际化本地化的色彩语义检测

阶段:AI 质量保障(出海前检查)

解决的问题:产品出海多个国家时,同一套配色在不同文化中可能表达相反含义(中国红涨绿跌 vs 美股绿涨红跌)。人工跨文化检查耗时且易漏。AI 系统批量扫描页面中的色彩语义,结合目标市场文化知识库,自动标记「高风险颜色组合」并提示增加文字/图标第二通道。

具体案例:某跨境理财 App 在上线美国市场前,AI 检测发现基金涨跌图仅用红绿区分,立即建议叠加「▲/▼」箭头,并在阿拉伯语版本中调整 RTL 布局下的焦点指示方向。上线后色盲与跨文化用户满意度提升 32%。

场景三:个性化无障浏览扩展

阶段:AI 个性化适配(运行时)

解决的问题:统一的页面无法同时满足视力正常、老花、白内障、色盲等多样化用户需求。AI 浏览器扩展读取用户视觉档案(自填问卷 + 环境光传感器),动态调整目标对比度,为低视力用户注入高对比主题,为色盲用户重映射颜色方案,保证实时可达标。

具体案例:一位 65 岁黄斑变性用户在阅读 AI 新闻产品时开启扩展,系统自动将正文对比度从 3.2:1 提升到 7.5:1,并把文字放大 1.4 倍、行距拉大——用户阅读时长从 2 分钟提升到 12 分钟,订阅转化率翻倍。

Python 演示

python63 行
# -*- coding: utf-8 -*-"""对比度计算器:计算任意两个颜色的 WCAG 对比度,并给出 AA/AAA 判定。"""def hex_to_rgb(hex_str):    """'#RRGGBB' -> (r, g, b),0-255 整数。"""    hex_str = hex_str.lstrip('#')    return tuple(int(hex_str[i:i+2], 16) for i in (0, 2, 4)) def rgb_to_linear(c):    """sRGB 通道值(0-1)转线性光。"""    c = c / 255.0    if c <= 0.03928:        return c / 12.92    return ((c + 0.055) / 1.055) ** 2.4 def relative_luminance(hex_str):    """计算 WCAG 相对亮度 L。"""    r, g, b = hex_to_rgb(hex_str)    return 0.2126 * rgb_to_linear(r) + 0.7152 * rgb_to_linear(g) + 0.0722 * rgb_to_linear(b) def contrast_ratio(c1, c2):    """计算对比度 (L1+0.05)/(L2+0.05),L1 为较亮者。"""    L1 = relative_luminance(c1)    L2 = relative_luminance(c2)    if L1 < L2:        L1, L2 = L2, L1    return round((L1 + 0.05) / (L2 + 0.05), 2) def simulate_deuteranopia(hex_str):    """红绿色盲(第二色觉)简化模拟:压缩 R/G 通道差异。"""    r, g, b = hex_to_rgb(hex_str)    nr = int(0.367 * r + 0.633 * g)    ng = int(0.633 * r + 0.367 * g)    nb = b    return '#%02X%02X%02X' % (nr, ng, nb) def wcag_level(c1, c2, large=False):    """返回 'AAA' / 'AA' / 'FAIL'。large 为大字号或 UI 组件。"""    cr = contrast_ratio(c1, c2)    aa = 3.0 if large else 4.5    aaa = 4.5 if large else 7.0    if cr >= aaa:        return 'AAA'    if cr >= aa:        return 'AA'    return 'FAIL' def main():    pairs = [        ('#818CF8', '#C7D2E4'),        ('#10B981', '#C7D2E4'),        ('#F43F5E', '#C7D2E4'),    ]    for fg, bg in pairs:        level = wcag_level(fg, bg)        print('文字 %s / 背景 %s -> 对比度 %s,级别 %s' % (fg, bg, contrast_ratio(fg, bg), level))    green = '#10B981'    red = '#F43F5E'    print('色盲模拟前红/绿对比:%s' % contrast_ratio(green, red))    print('模拟后红/绿对比:%s' % contrast_ratio(        simulate_deuteranopia(green), simulate_deuteranopia(red))) if __name__ == '__main__':    main()
目的:这是一个迷你版「无障碍巡检工具」——输入任意两个十六进制颜色,即可输出它们的 WCAG 对比度、AA/AAA 级别,并演示红绿色盲模拟后颜色对是否还能区分。
  1. def hex_to_rgb(hex_str):把 #RRGGBB 字符串解析成 RGB 整数组,是后续所有计算的地基。
  2. return tuple(int(hex_str[i:i+2], 16) for i in (0, 2, 4))每两位十六进制转一个十进制整数,一次生成三个通道值。
  3. def rgb_to_linear(c):sRGB 编码值到线性光的转换,先把 0-255 缩放到 0-1,再做分段线性化。
  4. if c <= 0.03928:暗部阈值判断,低于阈值用线性近似,高于阈值用 2.4 次幂曲线。
  5. return ((c + 0.055) / 1.055) ** 2.4伽马解码的标准公式,把「相机里看到的颜色」还原成「物理亮度」。
  6. 0.2126 * rgb_to_linear(r) + 0.7152 * rgb_to_linear(g) + 0.0722 * rgb_to_linear(b)加权求和,人眼对绿最敏感所以权重最高。
  7. def contrast_ratio(c1, c2):核心函数,计算两个颜色的 WCAG 对比度。
  8. if L1 < L2: L1, L2 = L2, L1确保亮者在分子,让对比度恒 ≥ 1。
  9. return round((L1 + 0.05) / (L2 + 0.05), 2)应用环境光修正后的对比度公式。
  10. def simulate_deuteranopia(hex_str):红绿色盲模拟,压缩红绿通道差异以便检查双通道冗余。
  11. nr = int(0.367 * r + 0.633 * g)简化色盲矩阵:红色锥缺失后,红色感觉主要由绿色通道补位产生。
  12. def wcag_level(c1, c2, large=False):输入两个颜色和是否大字,输出 AA/AAA/FAIL 判定。
  13. aa = 3.0 if large else 4.5大字号或 UI 组件的门槛放宽到 3:1,普通文本要求 4.5:1。

常见误区

误区「无障碍嘛,我把所有文字都做成纯黑配纯白,对比度 21:1,肯定最无障碍!」很多初学者认为对比度是越大越安全,于是界面一片黑白,甚至大面积纯白背景刺眼到没法看。

正解对比度是「可读性」和「舒适度」的平衡。纯黑纯白在阳光直射下确实清晰,但在暗环境中会像远光灯一样刺眼,长时间阅读产生残影与疲劳。WCAG 的目标是「达到阈值即可」——普通文本 4.5:1、大字 3:1,超过 AAA 的 7:1 也够用。大面积背景色应尽量柔和,把高对比留给关键信息,就像路灯够亮就好,而不是把灯塔探照灯装在路口。

为何常见:人们容易把「越大越好」的直觉套用到所有指标上,且测试时多在明亮环境下进行,忽略了暗环境下的眩光问题。

误区「我查过了,文字和背景对比度 6:1,远超标准,所以这个『红绿状态点』也没问题。」许多设计师只检查了正常视觉下的对比度,忽略了红绿色盲用户看到的可能是两个几乎相同的灰色小点。

正解对比度达标只是第一步。如果信息完全依赖颜色区分(红=错误、绿=成功),必须在色盲模拟工具下再测一次——模拟后的对比度仍须 ≥ 3:1。更稳妥的做法是永远叠加形状、文字或图案作为第二通道。就像信号灯除了红绿,还有位置和箭头。

为何常见:色盲模拟不是默认习惯,人们常用自己的视觉经验「脑补」所有人的体验,而正常视觉无法直觉体会色觉缺失的世界。

误区「我们设好了颜色 token,前端按规范写代码,后面就没我事了。」很多团队把无障碍归为「设计任务」或「前端任务」,结果上线后文案、图表、第三方组件处处翻车。

正解无障碍贯穿内容生产全链路:文案是否足够清晰(链接不能只写「点击这里」)、图表是否有数据标签、动效是否可关闭、AI 生成的内容是否满足对比度——这些都是「团队协作」的结果。最佳实践是把无障检查接入 CI/CD,谁提交谁负责,产品、设计、开发、测试共同背指标。

为何常见:无障碍常被理解为「美观层面的修饰」,而非「系统性的工程质量」,所以容易在部门间互相推诿。

误区「我把设计稿转成黑白图看了看,红色和绿色都能分清,所以色盲用户没问题。」这是把「去色」当成了「色盲模拟」。

正解灰度是等比例压缩所有颜色的亮度,而色盲是特定颜色通道的「换色」——红绿色盲看到的不是黑白电影,而是红绿被合并成黄褐色后、蓝色依然鲜艳的奇特世界。用 Figma 的色盲模拟插件、Stark、Color Oracle 等专业工具,才能准确看到红绿对在色盲眼中如何塌缩。就像模拟雨天开车,不能只把照片调暗,还要加上雨刮器和反光。

为何常见:人脑容易把「看不清颜色」等价于「变成黑白」,这是一种对感官缺失的简化想象,但生理机制完全不同。

误区「这段正文对比度 4.6:1,刚好过线,完美达标!」于是把一段 10px 的浅灰色辅助文字也套用 4.5:1 标准,结果实际可读性依然很差。

正解对比度和字号是「组合拳」。WCAG 的 4.5:1 是对普通字号的要求,而小字号、低亮度屏幕、远距离观看的场景需要更高对比度;反过来说,大字号可以放宽到 3:1,但也不能无限缩小字体去「蹭」这个宽松线。经验法则是:12px 以下的文字对比度至少 7:1,重要数据至少 4.5:1,且永远不要用纯灰色做次要文字。

为何常见:阈值思维让人产生「过线即安全」的错觉,忽略了真实使用环境中的亮度衰减、屏幕角度和用户视力差异。

面试题

Q1. WCAG AA 级别要求普通文本的对比度至少达到多少?

单选题 · easy

  • A.3:1 大字文本阈值
  • B.4.5:1 普通文本标准← 正确答案
  • C.7:1 高等级别参考
  • D.1.4:1 最低视觉要求

答案:B。WCAG 对普通文本的 AA 要求是 4.5:1,大字号和 UI 组件可放宽到 3:1,AAA 级才要求 7:1。1.4:1 是「勉强可感知」的参考线,不能算达标。就像路灯亮了但只够看到人影,看不清路牌。

Q2. 计算 WCAG 相对亮度时,权重最大的颜色通道是哪个?

单选题 · easy

  • A.红色通道最高
  • B.绿色通道权重高← 正确答案
  • C.蓝色通道最大
  • D.三通道均等分配

答案:B。人眼对绿光最敏感,所以绿色通道权重 0.7152 远高于红色 0.2126 和蓝色 0.0722。这也解释了为什么同样亮度的红蓝两色,观感亮度差异巨大。

Q3. 红绿色盲用户最容易忽略下列哪种界面信息?

单选题 · mid

  • A.仅靠红绿区分的状态点← 正确答案
  • B.带图标的错误提示
  • C.附有文字说明的标签
  • D.圆圈变方块的形状变化

答案:A。红绿色盲把红绿信息压缩成相近的灰黄色,仅靠这两种颜色区分的圆点在色盲视界里几乎相同。图标、文字、形状都是第二通道,不会被色盲影响。

Q4. 以下哪些做法能真正提升低视力用户的可用性?

多选题 · mid

  • A.支持 200% 文本缩放← 正确答案
  • B.提供高对比度模式← 正确答案
  • C.用细小灰色字辅助
  • D.缩小点击目标节省空间

答案:AB。WCAG 1.4.4 要求文本可缩放 200%,高对比度模式也是低视力用户的核心依赖。细小灰色字是低视力的大敌,缩小点击目标则让手部抖动用户更难操作。

Q5. WCAG 1.4.11 对 UI 组件和图形对象的对比度最低要求是?

单选题 · mid

  • A.1.4:1 可见性底线
  • B.3:1 组件边界标准← 正确答案
  • C.4.5:1 普通文本
  • D.7:1 最高安全级

答案:B。非文本对比度(按钮边框、图标、焦点环)要求 3:1,比正文的 4.5:1 宽松,因为组件只需「可识别边界」而非「清晰阅读」。就像路缘石的黄黑条纹不需要看清文字,只要看出边界。

Q6. 产品国际化时,以下哪些是必须考虑的色彩无障碍问题?

多选题 · hard

  • A.颜色在不同文化的语义← 正确答案
  • B.多语言文案长度膨胀← 正确答案
  • C.RTL 布局的镜像适配← 正确答案
  • D.减少所有图片的使用

答案:ABC。颜色语义(红涨绿跌 vs 绿涨红跌)、文案膨胀(德语比英文长 30%)和 RTL 镜像都会影响视觉呈现与对比度。减少图片不是无障碍手段,反而可能降低信息可理解性。

Q7. 键盘焦点指示环的可见性属于哪类对比度要求?

单选题 · easy

  • A.文本对比度要求
  • B.非文本对比度要求← 正确答案
  • C.色盲适配规范
  • D.国际化适配规范

答案:B。焦点环是 UI 组件的视觉边界,属于 WCAG 1.4.11 非文本对比度范畴,需达到 3:1。它帮助键盘用户知道「我现在站在哪个路口」。

Q8. AI 自动检测工具在无障碍领域的主要优势是什么?

单选题 · mid

  • A.完全替代人工评审
  • B.快速扫描大量页面定位违规← 正确答案
  • C.无需结合团队经验
  • D.自动生成无障碍文案

答案:B。AI 检测的核心价值是「批量 + 快速」扫描并定位对比度违规,但无法完全替代人工判断,复杂场景仍需设计师经验。它像巡检无人机,能快速发现路灯坏了,但换灯泡还得靠人。

Q9. 关于色盲模拟,下列说法正确的是?

多选题 · hard

  • A.灰度预览可以替代模拟
  • B.模拟能揭示红绿信息丢失← 正确答案
  • C.模拟后仍需检查对比度← 正确答案
  • D.色盲看不到任何颜色

答案:BC。灰度是去色,色盲是换色,二者机制不同;模拟后的颜色对仍需满足 3:1 对比度才能保证信息不丢失。绝大多数色盲不是全盲色觉,只是某些颜色对难以区分。

Q10. sRGB 线性化公式中的阈值 0.03928 代表什么?

单选题 · extreme

  • A.人眼暗视觉的绝对阈值
  • B.伽马编码与线性近似的交点← 正确答案
  • C.显示器的最低亮度标准
  • D.蓝色通道特有的临界值

答案:B。sRGB 的伽马曲线在暗部接近线性,0.03928 是曲线与直线近似的分界点:低于此值用线性公式 c/12.92,高于此值用 2.4 次幂曲线。这是数学上的拟合交点,并非生理阈值,也不针对特定通道。