关于 accessibility
面向设计师和开发者的无障碍技能,用于构建和审查 Web 界面。它以屏幕阅读器体验为重点,提供 WCAG 检查、参考模式和对比度检测脚本。
主要功能
- 01屏幕阅读器优先的审查指南
- 02WCAG 审计优先级与清单
- 03ARIA 与焦点管理模式
- 04屏幕阅读器手动测试步骤
- 05对比度检测脚本
适用场景
- 01审查现有界面的无障碍问题
- 02检查键盘与屏幕阅读器操作
- 03按 WCAG 对比度阈值验证颜色组合
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ connorads/ dotfiles --skill accessibility安装后在 Claude Code 中输入/accessibility确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/aria-patterns.mdcommon-fixes.mdfocus-management.mdscreen-readers.mdwcag-checklist.mdscripts/contrast-check.pytests/test_contrast_check.py详细介绍
无障碍
真正做好 Web 无障碍,意味着残障人士能够浏览、理解和操作你的 UI,包括屏幕阅读器用户、仅使用键盘的用户,以及有低视力、运动或认知障碍的人士。这项技能采用屏幕阅读器优先的视角,因为它能最快暴露结构性问题;但低视力用户(对比度、缩放、重排)和认知障碍用户同样重要。事实上,低对比度文本是 Web 上最常见的障碍,影响约 84% 的首页。WebAIM Million 一直发现,约 96% 的首页存在可检测到的 WCAG 问题;而仅六类问题——低对比度文本、缺失替代文本、缺失表单标签、空链接、空按钮和缺失文档语言——就占所有检测到的问题的约 96%,且自发布 WebAIM Million 结果以来,每年都位居问题榜首(见链接)。采用正确的思维模型,大多数问题都可以避免。
核心思维模型
屏幕阅读器会将二维页面线性化为一维音频流。盲人用户无法一次看到整个页面,而是通过键盘快捷键,按顺序浏览标题、地标、表单字段、链接和交互控件。你做出的每个决定都应回答这个问题:“屏幕阅读器会播报什么?单独听到这些内容时,是否讲得通?”
由此得出的三条规则:
- 语义优先于样式——优先使用原生 HTML 元素(
<button>、<nav>、<h2>),再考虑 ARIA。原生元素自带键盘支持、无障碍名称和正确的角色。 - 元素必须携带上下文——通过 Tab 键或链接列表导航的屏幕阅读器用户,看到的元素与其视觉邻近内容是分离的。标签、描述和状态必须以编程方式关联,而不能依赖相邻位置来暗示。
- 必须播报动态变化——只有焦点移至新内容,或实时区域播报变化时,屏幕阅读器才会注意到内容变化。静默的 DOM 修改对 AT 不可见。
审查现有 UI 时
按以下优先顺序检查——先修复关键问题,再处理影响较小的细节:
| 优先级 | 类别 | WCAG 级别 | 参见 |
|---|---|---|---|
| 1 | 无障碍名称(按钮、输入框、链接) | A | references/aria-patterns.md |
| 2 | 键盘可操作性(所有交互元素) | A | references/focus-management.md |
| 3 | 焦点管理(对话框、SPA、实时区域) | A/AA | references/focus-management.md |
| 4 | 语义结构(标题、地标、列表) | A | references/wcag-checklist.md |
| 5 | 表单错误和验证 | A/AA | references/common-fixes.md |
| 6 | 颜色对比度和视觉状态 | AA | references/wcag-checklist.md |
| 7 | 动态内容播报 | AA | references/aria-patterns.md |
| 8 | 图像和媒体 | A | references/wcag-checklist.md |
| 9 | 动效、闪烁和计时(减少动态效果、癫痫安全、自动更新内容) | A/AA | references/wcag-checklist.md |
引用确切的错误代码片段,注明 WCAG 标准条款,并提出最小可行的修复方案。不要重构无关代码。
构建新 UI 时
快速决策树
Need an interactive control?
↓
Does a native HTML element do this? → YES → Use it. Done.
↓ NO
Use the correct ARIA role + required attributes + keyboard handler.
Adding dynamic content?
↓
Does focus move to the new content? → YES → No live region needed.
↓ NO
Is it a transient status (toast, cart count, form error)?
→ Use aria-live="polite" (or role="alert" for errors)
Opening a dialog/modal?
→ Trap focus inside. Restore focus to trigger on close.
→ See references/focus-management.md
发布任何交互组件前的必检项
- 每个 input、select、textarea 都有对应的
<label>(不能只有占位符) - 每个按钮都有可访问名称(文本内容、
aria-label或aria-labelledby) - 每个纯图标控件都有
aria-label;图标有aria-hidden="true" - 所有交互元素都能清晰显示焦点(除非有替代样式,否则绝不使用
outline: none) - Tab 顺序合理,并与视觉顺序一致
- 所有指针交互都有键盘等效操作
- 没有大于 0 的
tabindex - 交互目标至少为 24×24 CSS px,或彼此间隔足够(WCAG 2.5.8)
- 非必要动效遵循
prefers-reduced-motion;任何内容每秒闪烁不超过三次(WCAG 2.3.1)
五种影响最大的屏幕阅读器故障(及其修复方法)
从屏幕阅读器的角度来看,使用此技能时最常遇到的就是这些故障。(全站出现最多的故障——低对比度文本、缺少 alt 文本——将在下文的“颜色与对比度”和“图像”部分介绍。)
- 纯图标按钮没有可访问名称——只会播报“按钮”;需要在按钮上添加
aria-label,并在图标上添加aria-hidden="true"。 - 输入框没有标签——占位符不是标签;需要关联的
<label for>。 - 将 div 或 span 用作按钮——不支持键盘操作,也没有角色;应使用
<button>。 - 错误信息未与对应字段关联——视觉上相邻的文本不会被播报;使用
aria-describedby+aria-invalid进行关联。 - 动态内容更新时没有播报——如果没有实时区域,辅助技术(AT)无法感知 DOM 变化。
这五种问题的修复前后对比见:references/common-fixes.md(分别对应修复 1、2、5、3 和 23)。
屏幕阅读器测试
自动化工具只能发现约 30-40% 的无障碍问题。其余问题需要通过辅助技术(AT)测试。
最低可行测试矩阵:
- NVDA + Firefox 或 Chrome(Windows)——免费、严格,是两种最常用的桌面屏幕阅读器之一
- VoiceOver + Safari(macOS/iOS)——在 Apple 平台上占主导地位的屏幕阅读器
- 面向企业场景的 JAWS + Chrome——另一款领先的桌面屏幕阅读器
需要手动测试的核心导航模式:
- 使用 Tab 遍历所有交互元素——名称和角色是否播报正确?
- 按
H按标题导航——页面结构是否合理? - 按
D按地标导航——各区域是否有清晰的标签? - 打开并关闭所有对话框——焦点是否会被限制在对话框内,然后恢复?
- 提交包含错误的表单——错误消息是否会被播报?
- 触发任何动态内容更新——变化是否会被播报?
有关 NVDA/JAWS/VoiceOver 命令、浏览模式与表单模式,以及测试脚本,请参阅 references/screen-readers.md。
ARIA:规则
规则 0: 如果原生 HTML 能解决问题,就不要使用 ARIA。错误使用 ARIA 比不使用更糟。
规则 1: aria-label 和 aria-labelledby 提供可访问名称(元素是什么)。
规则 2: aria-describedby 提供补充说明(元素做什么或需要什么)。
规则 3: 非紧急更新使用 aria-live="polite";错误使用 role="alert"(隐式为 assertive)。
规则 4: 实时区域必须在页面加载时就存在于 DOM 中——向其中注入文本,不要注入区域本身。
规则 5: aria-hidden="true" 会将元素彻底移出 AT 树。绝不要将其应用于可聚焦元素。
完整的 ARIA 模式库 → references/aria-patterns.md
视觉隐藏的内容
若要让屏幕阅读器能读取内容,但在视觉上隐藏内容,请使用 .visually-hidden 工具类。标准 CSS 见 references/common-fixes.md 中的 “The Visually Hidden Utility Class”。
适用于:跳过链接、补充链接上下文(“阅读更多关于缓存”)、因翻译原因不便使用 aria-label 的图标按钮标签。
不要用于:视力正常的用户也需要的内容。对某一群体隐藏有意义的内容会造成差异,而非实现无障碍。
颜色与对比度(WCAG AA)
| 内容类型 | 最低比例 |
|---|---|
| 正文(<18pt / 24px,且 <14pt 粗体 / 18.5px) | 4.5:1 |
| 大号文本(≥18pt / 24px,或 ≥14pt 粗体 / 18.5px) | 3:1 |
| UI 组件(边框、图标、焦点环) | 3:1 |
| 占位文本 | 4.5:1 |
| 禁用元素 | 豁免 |
切勿仅通过颜色传达信息——始终搭配形状、图案或文本标签。
尊重用户的颜色偏好:支持 prefers-color-scheme,并在 Windows 高对比度模式 / forced-colors: active 下进行测试,而不是覆盖它(切勿对有意义的内容使用 forced-color-adjust: none)。请参阅 references/wcag-checklist.md。
使用 accessibility 技能目录中的工具检查精确的前景色/背景色组合:
python3 scripts/contrast-check.py '#333333' '#ffffff'
python3 scripts/contrast-check.py '#767676' '#ffffff' --json
python3 scripts/contrast-check.py '#949494' '#ffffff' --target large-text
python3 scripts/contrast-check.py '#949494' '#ffffff' --target ui-component
使用 --target normal-text(默认值)、large-text、ui-component、
aaa-normal-text 或 aaa-large-text,让退出状态符合相应的阈值。不要将对比度数值向上取整。测得的 4.499:1 不符合 4.5:1 的要求。
**WCAG 2 AA(本表)是唯一的符合性目标。**其比例计算是对称的,不考虑极性,因此可能会高估某些深色模式下的组合效果——如果某个组合虽然通过检测,但在深色背景上仍显得不易阅读,应将其视为设计问题,并使用感知工具(APCA)进行检查。APCA 是仍处于草案阶段且未注明日期的 WCAG 3 的候选算法(它甚至曾从 2023 年 7 月的草案中撤下,等待达成共识)——它仅用于辅助设计,绝不能替代合规性检查。
参考文件
| 文件 | 内容 |
|---|---|
| references/screen-readers.md | NVDA/JAWS/VoiceOver 命令、浏览模式与表单模式、各组件类型的测试脚本 |
| references/aria-patterns.md | ARIA 角色、标签层级、实时区域模式、复杂组件的 ARIA(组合框、标签页、树) |
| references/focus-management.md | 模态框焦点陷阱、SPA 路由变更时的焦点处理、跳过链接、焦点恢复模式 |
| references/wcag-checklist.md | WCAG 2.2 AA 逐项检查清单及通过/失败示例 |
| references/common-fixes.md | 针对 20 种最常见审查问题的代码级修复模板 |
| scripts/contrast-check.py | 用于前景色/背景色十六进制颜色对的确定性 WCAG 对比度检查器 |
| tests/test_contrast_check.py | 检查器的行为测试(比例、退出代码、十六进制颜色解析)- uv run --with pytest -- pytest tests/ |