AI 生成界面的无障碍漏洞怎么查
文章梳理 AI 编程助手常见的四类无障碍错误,并对应 WCAG 条款说明检查方法。摘录重点展示自定义按钮缺少键盘支持,以及 aria-label 与可见文字不一致的问题。
完整中文译文
AI 生成的组件,鼠标点得动、页面看着正常,仍然可能让键盘用户和语音控制用户卡住。作者列出四类常见的无障碍错误:用 div 模拟按钮、乱加 aria-label、把 placeholder 当标签,以及清掉焦点轮廓。
它们的共同问题是:视觉验收很容易放行,操作方式一变就暴露缺陷。对经常让 AI 写 React 组件的开发者,这篇文章最有用的部分,是把检查拆成了源码、键盘操作和浏览器渲染三个层面。
点得动的组件,为什么不一定能用
第一类错误,是给 <div> 加上 onClick,把它当按钮。鼠标可以触发事件,键盘用户却可能既无法通过 Tab 到达它,也无法用 Enter 或 Space 激活它。作者将其对应到 WCAG 2.1.1 和 4.1.2。
只补 role="button" 仍然不够。它声明了角色,却没有自动补齐焦点和键盘行为。ARIA 能告诉辅助技术「这是什么」,但不会替你实现完整交互。
下面这行用原生按钮解决了这组问题:
<button type="button" className="btn" onClick={save}>Save</button>
要看的是 <button> 本身:它已经具备焦点、键盘激活和按钮语义。作者建议,只有原生元素无法满足需求时,才考虑用 role 和 tabIndex 自己拼装。
另一类错误发生在 CSS。生成代码里的 *:focus { outline: none; },会把键盘用户判断当前位置的视觉提示清掉,对应 WCAG 2.4.7。
如果默认轮廓不符合设计,可以替换成明确的焦点样式:
:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
}
要看的是 :focus-visible:它让浏览器在需要显示焦点提示时应用样式。这里的 2px 轮廓和偏移提供了一种写法,具体页面里是否清楚可见,还要实际检查。
加了 ARIA,为什么反而可能更难操作
第二类错误,是按钮显示「Buy now」,却写着 aria-label="Add product to basket"。
aria-label 会替代可见文本,成为辅助技术识别控件的无障碍名称。用户看到「Buy now」,通过语音说出这个名字时,控件却可能无法匹配。
WCAG 2.5.3 的 Label in Name 要求,是无障碍名称包含可见标签。最直接的处理方式是删除多余的 aria-label,让按钮文本自然成为名称。如果确实需要补充商品信息,作者给出的写法是 aria-label="Buy now: Linen shirt",把可见文字放在名称开头。
无障碍属性的数量,不能代表组件的无障碍质量。
第三类错误是把 placeholder="Email address" 当成输入框标签,对应 WCAG 3.3.2 和 1.3.1。提示文字在输入后消失,通常对比度也偏低,无法承担稳定的字段说明。
作者的修复方式是提供可见的 <label for="email">,通过输入框的 id="email" 建立关联,并使用 type="email" 和 autocomplete="email"。其中,标签关联才是在解决「这个输入框是什么」的问题;输入类型和自动填充属性不能代替标签。
合并前,要查源码,也要操作页面
作者建议组合使用几种检查,因为它们覆盖的问题不同。
编辑器里的 eslint-plugin-jsx-a11y 可以提示非交互元素上的点击事件、缺少标签的输入框等问题。提示词和代码审查也应优先要求原生元素,例如直接指定 <button> 或原生 <dialog>。
接着要做一次键盘检查:用 Tab 穿过新组件,确认控件能够到达、能够操作,而且焦点位置可见。
浏览器检查则负责确认最终结果。作者指出,第 1、2、4 类问题涉及实际可聚焦状态、计算后的名称和焦点样式,仅看源码不足以确认。文中介绍了 ADAGuard,称它会在真实浏览器中检查这些问题,包括 Label in Name,并提供免费页面扫描。但原文没有给出检测覆盖率或对照结果。
作者还反对把运行时修补脚本当作兜底方案:脚本在访问者浏览器中修改页面,仓库里的错误源码仍然存在,后续 AI 继续参考这些代码时,问题也可能延续。
我的判断
这篇文章最扎实的建议,是优先使用原生 HTML,并把键盘操作纳入验收。对按钮这类已有标准元素的控件,自己补角色、焦点和按键处理,会增加需要维护的行为。
但原文不是一份实测报告。作者没有给出模型版本、生成样本量或错误频率;「AI 经常犯这些错」属于经验观察。ADAGuard 的介绍也没有附带与其他工具的对照数据,不能据此认定它检查得更全面。
结尾所说 AI 无法发现自己写的组件不能用键盘操作,也有些绝对。更可靠的判断是:一次代码生成并不能证明交互可用,仍需要测试证据。发现明确问题后,再让 AI 批量应用已知修复,才比较容易验收。
能拿来做什么
- 让 AI 生成 React 交互组件时,明确要求优先使用原生
<button>,为输入框提供可见且关联的标签,并保留可见焦点。 - 在 JSX 项目中接入
eslint-plugin-jsx-a11y,把规则提示作为源码检查的一部分,再对新组件做一次 Tab、Enter 和 Space 操作检查。 - 审查 AI 添加的
aria-label时,对照页面可见文字,确认名称包含可见标签,并删除没有必要的覆盖。 - 批量修复前先确认错误类型,再让 AI 修改同类代码,最后回到渲染页面验证名称、焦点和操作行为。