USWDS 无障碍开发规范:面向仓库贡献者的 WCAG 2.1 AA 实操指南

原创2026-10-14 18:03:261,227 阅读
文章标签:UI组件设计系统前端

USWDS 无障碍开发规范:面向仓库贡献者的 WCAG 2.1 AA 实操指南

导读

本文围绕 USWDS(U.S. Web Design System)仓库内的无障碍开发规范文档(.agents/skills/uswds-accessibility/SKILL.md)展开,系统梳理了面向仓库贡献者(而非下游应用消费方)的无障碍标准、不可妥协原则、高危组件清单、验证闭环与常见反模式。读完本文,你将掌握:如何在修改交互组件(modal、combo-box、date-picker、accordion 等)时守住 WCAG 2.1 AA 底线,如何运行并解读仓库内置的自动化无障碍测试(npm run test:a11y),以及如何用手动辅助技术测试矩阵完成对焦点管理、键盘行为与屏幕阅读器播报的最终验收。文中所有结论均可在当前仓库的源码与测试用例中找到对应证据。

适用对象说明:本文规范针对在 USWDS 仓库内工作(构建组件)的编码 Agent 与开发者。若你的团队只是在应用中消费 USWDS,无障碍验收逻辑并不相同,需要另行参考 designsystem.digital.gov 的公开文档。


1. 标准与底线:WCAG 2.1 AA 与法律下限

1.1 质量线:WCAG 2.1 AA 起步

规范文档给出的核心标准非常明确:

  • 最低门槛(Bar):WCAG 2.1 AA。
  • 若组件本已追求更高目标(WCAG 2.2 / AAA),或修复成本很低,应优先采用更高标准。
  • 法律下限(Legal floor):Section 508 采纳的是 WCAG 2.0 AA;《美国残疾人法案》(ADA)采纳的是 WCAG 2.1 AA。因此仅满足 508 并不等于达到 USWDS 的质量线——质量线始终是 WCAG 2.1 AA 起步。

这里的关键区别在于:法律合规 ≠ 产品无障碍质量。符合 508 只是不违法的起点,USWDS 的组件质量标准高于法律底线。

1.2 自动化测试的定位

仓库在 package.json 中定义了无障碍自动化测试脚本:

"test:a11y": "storybook build -o _site && concurrently -k -s first -n \"SB,TEST\" \"http-server _site --port 6006 --silent\" \"wait-on --timeout 30000 http://127.0.0.1:6006 && test-storybook --url http://127.0.0.1:6006\""

从脚本可见其技术链路:Storybook 构建 + 静态服务器 + Playwright 驱动的 test-storybook(集成 Axe)。规范文档明确:npm run test:a11y 的失败是阻塞性的(blocking),而非建议性(advisory)。但与此同时:

通过 Axe 是必要不充分条件。

即 Axe 全绿不代表无障碍验收完成——焦点行为、键盘操作、屏幕阅读器播报这类需要人工判断的维度,自动化扫描覆盖不到(详见第 5 节验证闭环)。test:ci 脚本(npm run lint && gulp test && npm run test:dist && npm run test:a11y && npm run build:html)也将 test:a11y 纳入了 CI 全链路。

1.3 术语表:先统一语言

规范文档定义了四组关键术语,在仓库评审与 PR 交流中应统一使用:

  • WCAG:Web Content Accessibility Guidelines,成功标准引用格式为 SC X.X.X(例如 SC 2.4.7)。USWDS 目标为 WCAG 2.1 AA 起步。
  • 辅助技术(Assistive technology):帮助用户与内容交互的软硬件(屏幕阅读器、放大镜、语音控制、开关访问等),不等于自动化无障碍扫描。
  • 手动辅助技术测试(Manual assistive technology testing):用真实工具与浏览器进行人工验证(纯键盘、屏幕阅读器组合、缩放、强制颜色模式)。交互行为变更时必须执行;自动化 npm run test:a11y 不能替代它。
  • 屏幕阅读器(Screen reader):验证矩阵中使用的辅助技术类型(VoiceOver、NVDA、TalkBack)。规范中"screen reader"默认指具名的浏览器 + 屏幕阅读器组合,除非变更纯属视觉范畴。

2. 不可妥协的七条原则(Non-negotiables)

规范文档从 USWDS 无障碍原则中提炼出**不得回退(do not regress)**的七条底线,任何修改都必须守住:

  1. 键盘焦点顺序:焦点遵循逻辑、可预测的顺序,且焦点指示器始终可见(WCAG 2.4.7;不得遮挡焦点,SC 2.4.11)。
  2. 禁止仅靠视觉传达含义:含义不得仅由视觉样式(颜色、形状、位置)传达;文本与 UI 组件对比度满足 WCAG 最低要求——普通文本 4.5:1、大文本与 UI 组件/图形 3:1(SC 1.4.3、1.4.11)。
  3. 状态变更播报:页面与组件状态变化需在用户需要时向辅助技术播报(状态消息,WCAG 4.1.3)。
  4. 非文本内容的文本替代:非文本内容必须有合适的文本等价物。
  5. 关键信息不依赖 hover:关键信息不能仅靠悬停呈现。
  6. 触控与纯键盘双支持:触控与纯键盘交互都必须完整支持;可行时触控目标最小为 24×24 CSS px(WCAG 2.2 SC 2.5.8)。
  7. 尊重设备与浏览器无障碍设置(WCAG 1.4.4、1.4.10、1.4.12;涉及动画时 SC 2.2.2)——布局与功能必须在用户自定义设置下依然可用,而非假设默认浏览器/OS 配置。具体拆解为:
    • 文本缩放与回流(reflow):400% 缩放 / 320px 宽度下不得丢失内容或功能;优先使用 rem/em 而非固定 px 来设定文本与间距。
    • 减弱动态效果(Reduced motion):尊重 prefers-reduced-motion;不得仅靠动画传达含义;确需保留的关键动画必须显式标注。
    • 强制颜色 / 高对比度(Forced colors):测试纯图标控件与 CSS 生成指示器;当系统颜色接管时,不得仅依赖 background-color 表达状态。
    • 指针 / 输入假设:同时支持键盘与触控;不得要求仅 hover 交互(见第 5 条)或精细指针精度。
    • 禁止在组件 CSS 中:禁用缩放、覆盖用户文本间距、重置 OS 字号或对比度设置。

2.1 仓库中的原则落地示例:文本替代

以 Banner 组件为例,usa-banner.twig 中的锁形图标通过 role="img"、aria-labelledby 与 <title>/<desc> 提供了完整文本替代;而装饰性国旗小图直接使用 aria-hidden="true" + alt="" 标记为纯装饰。这正是原则 4"非文本内容文本替代"在模板层的实际体现——装饰性内容隐藏、信息性内容命名。


3. 适用范围防火墙(Scope firewall)

USWDS 交付无障碍组件,但这不意味着使用它的站点自动满足 Section 508。规范明确两条红线:

  • 不得把组件级修复当作关闭下游项目应用级无障碍 issue 的依据。
  • 不得仅凭"使用了 USWDS"或"本仓库 Axe 通过"就宣称整个产品"508 合规"或"符合 WCAG"。

这条防火墙与本文第 8 节的反模式相互呼应:产品级合规声明需要应用层面的整体验收,组件库层面的通过与否不能替代。


4. 何时适用本规范:变更触碰面清单

规范文档列出的变更类型,只要触碰以下任一领域,就必须按本文流程执行:

  • 交互行为、焦点或键盘处理
  • aria-*、role、名称、描述、live region
  • 显示/隐藏模式(hidden、aria-hidden、data-modal-hidden、disclosure)
  • 仅供屏幕阅读器的文本(.usa-sr-only 及同类)
  • 颜色对比度、焦点可见性或触控目标尺寸
  • a11y 测试、Storybook a11y stories,或 PR 中的手动辅助技术测试说明

反之,若变更与本规范无关(tokens、纯 Sass 颜色、不影响屏幕阅读器的文档 typo),应明说并停止,不要强行套用无障碍评审。


5. 高危组件清单(High-risk components)

规范文档给出了一张"需格外小心"的组件表,每个条目都对应仓库中的真实源码。修改这些组件前,优先阅读现有组件 JS 与测试。

组件区域 需要警惕的点 仓库源码佐证
Modal 焦点陷阱、初始焦点、Escape、焦点恢复到打开者;非 modal 元素的 aria-hidden/data-modal-hidden 必须在关闭时清除——即使打开者节点已被移除 usa-modal/src/index.js、modal.spec.js
Combo box Listbox/popup 语义、过滤播报、指针与键盘行为对齐 usa-combo-box/src/index.js 中 aria-expanded、aria-activedescendant、role="listbox"
Date picker / date range Dialog 或 grid 键盘模型、禁用日期、焦点返回 usa-date-picker/src/index.js 中 aria-hidden 与 Escape 处理
Accordion aria-expanded、button/heading 模式、多选 vs 单选 usa-accordion/src/index.js 中 EXPANDED 常量与 data-allow-multiple 开关
Header / nav / language selector 菜单、焦点陷阱复用、移动端开关 usa-header/src/index.js 中 aria-hidden 与 FocusTrap
File input、character count、validation live region、错误关联(aria-describedby)、状态文本 usa-character-count/src/index.js、usa-validation/src/index.js
Table(可排序) 列表头按钮语义(aria-sort)、排序状态播报、排序控件键盘可操作性 usa-table/src/index.js
Tooltip hover 和 focus/关闭支持;绝不可作为关键信息的唯一来源;不得造成键盘陷阱 usa-tooltip/src/index.js
Banner "如何确认这是官方站点"展开/收起的 disclosure 语义 usa-banner/src/usa-banner.twig 中 aria-expanded/aria-controls 按钮
Pagination 当前页指示(aria-current="page")、每链接的可访问名称 usa-pagination/src/includes/_pagination-button.twig
Radio / checkbox 组、fieldset fieldset/legend 分组、组级错误关联 各表单组件的字段集模板

5.1 高频共享工具:底层实现速览

上述组件频繁依赖 packages/uswds-core/src/js/utils/ 下的五个共享工具:

  • focus-trap.js:通过 FOCUSABLE 选择器(a[href]、非 disabled 的 input/select/textarea/button、iframe、[tabindex="0"]、[contenteditable] 等)计算首/末可聚焦节点,实现 Tab 循环(正向到末位回绕到首位、反向同理),并支持注入 Escape 等附加按键绑定与 autoFocus 选项。
  • behavior.js:事件委托框架——把 { 事件: { 选择器: 回调 } } 规范化为 addEventListener 参数;on()/off() 控制组件初始化与销毁,是 focus-trap 中 update(isActive) 开关背后的机制。
  • keymap、active-element、toggle:分别负责按键映射、活动元素查询与布尔属性切换。

以 Modal 为例,index.js 中 modal.focusTrap = FocusTrap(targetModal, { Escape: onMenuClose }) 并调用 modal.focusTrap.update(safeActive),即把 focus-trap 的 Tab 回环与 Escape 关闭绑定到 modal 的开关生命周期上。而对应的 modal.spec.js 用 Mocha + jsdom 逐一断言了"打开时 aria-hidden="true" 写入非 modal 兄弟节点、初始焦点落在 footer 按钮、关闭后 aria-hidden 移除、焦点恢复给打开者"等行为——这些测试正是规范第 5 节"关注点"的自动化镜像。


6. 验证闭环(Verification loop)

规范明确:不得在完成下述相关步骤(或给出明确延后理由)之前宣布无障碍修复完成。整个闭环分四步:

6.1 第一步:优先复用既有模式,而非新造 ARIA

  • 与仓库内兄弟组件及 APG(Accessible Rich Internet Applications Authoring Practices)对齐的模式保持一致。
  • 避免"ARIA 汤"(ARIA soup):当可见标签或原生语义已能为控件命名时,不要再加 aria-label 去"堵住"检查工具。

6.2 第二步:仓库内单元测试(Mocha + jsdom)

行为变更时必须新增或更新 Mocha + jsdom 测试,参照 usa-accordion/src/test/ 或组件既有 specs。测试必须覆盖:焦点返回、Escape、打开/关闭属性清理、键盘路径(当这些正是 bug 所在时)。

单测运行示例(仓库规范原样给出):

npx mocha --require jsdom-global/register packages/<pkg>/src/test/<name>.spec.js

6.3 第三步:自动化无障碍扫描

  • 完整套件:npm run test:a11y(依赖 Storybook 构建与 Playwright 浏览器,速度慢)。当 markup/roles 变更时,或宣称 CI 无障碍绿灯前运行。
  • 在 PR 中说明:本地跑了什么、CI 将跑什么。

6.4 第四步:手动辅助技术测试(交互行为变更时必做)

自动化扫描不是焦点、键盘、对比度或播报变更的签字依据。实质性交互修复的最低手动测试矩阵为:

  • 纯键盘:Tab、Shift+Tab、Enter/Space、Escape、方向键(适用处)
  • 一组屏幕阅读器组合:VoiceOver + Safari,或 NVDA + Firefox(或 Chrome)
  • 缩放/回流:400% 缩放 / 320px 视口宽度——确认无内容或功能丢失(WCAG 1.4.10、1.4.4)
  • 强制颜色模式:若变更新增或改动纯图标控件、CSS 生成(::before/::after)内容,需在 forced-colors / Windows 高对比度模式抽查
  • 触控/手势:若变更影响触控或手势行为,需在桌面组合之外追加移动端屏幕阅读器一轮(VoiceOver + iOS Safari,或 TalkBack + Chrome)

PR 中必须写明:

  1. 你验证了什么
  2. 使用的浏览器 + 辅助技术
  3. 哪些问题是 develop 分支上已有的,哪些是本次引入的
  4. 局限 / 不在范围内

代码评审(uswds-code-review gate 16b)应路由手动辅助技术测试,而不是仅凭 diff 凭空判定 pass/fail——这正是本 skill 与代码评审技能的分工:无障碍判断归本技能,代码评审遇到辅助技术行为问题转交本技能处理。


7. 反模式清单(Anti-patterns):禁止行为

规范文档列出以下禁止行为,均可直接作为 PR 自检项:

  • 用 aria-hidden 隐藏内容来"骗过"Axe,却没有对应的取消隐藏路径
  • modal/dialog 关闭后页面残留 aria-hidden(尤其当打开者节点已被移除时)
  • 用 div + 点击处理器替换原生 <button> / <a> / <input>
  • 仅靠 title 承担关键可访问名称
  • 用 polite live region 播报每次击键,而一个状态变更播报就足够(保持 WCAG 4.1.3 状态消息本意)
  • 设置正数 tabindex(tabindex > 0)来强造自定义顺序,而非修正 DOM/源码顺序
  • 抑制默认焦点轮廓却没有合规的自定义指示器(WCAG 2.4.7 / 2.4.11)
  • 仅依赖 hover 的 tooltip 或菜单,没有 focus 触发的等价交互
  • 上线新的纯图标控件或 CSS 生成内容指示器,却未检查 forced-colors / Windows 高对比度模式
  • 仅凭组件使用或 Axe 通过就断言产品级 508 合规

8. 输出期望:评审意见的四个显式要素

应用本技能时,输出必须明确以下四要素,缺一不可:

  1. 风险(Risk):涉及哪条不可妥协原则或哪个高危组件区域
  2. 变更(Change):markup / 行为 / 测试发生了什么变化
  3. 证据(Evidence):跑过的测试、手动辅助技术测试矩阵(含缩放/回流、forced-colors、移动端屏幕阅读器测试,如适用),或延后理由
  4. 路由(Routing):若仍需真实辅助技术环境验证,应写明"Needs accessibility specialist assistive technology verification"并列出矩阵——不得仅凭代码就软性宣称"LGTM for assistive technology behavior"。

9. 与仓库其他约定的关系

  • 根 Agent 指南:仓库环境与常规设置见根目录 AGENTS.md。
  • 代码评审技能:PR 校准与非无障碍门禁见 .agents/skills/uswds-code-review/;本技能与之互补,承接其 gate 16 中的无障碍判断职责。
  • 上游上下文:本规范源于 USWDS 无障碍实践演进(对应上游 issue #6749),公开的用户侧无障碍说明以 designsystem.digital.gov 文档为准(当前仓库只读,不提供外链展开)。

结语

USWDS 的无障碍开发规范给出了一个可执行的分层模型:WCAG 2.1 AA 质量线 → 七条不可妥协原则 → 高危组件专项清单 → 四步验证闭环(模式复用 → Mocha 单测 → Axe 自动化 → 手动矩阵)→ 反模式禁令。对仓库贡献者而言,核心心法是两条:其一,自动化测试(npm run test:a11y)是必要不充分条件,焦点/键盘/播报类结论必须落到真实辅助技术矩阵;其二,组件级无障碍 ≠ 产品级合规,评审意见必须区分"已有问题"与"本次引入",并如实标注需要专业无障碍专家验证的部分。

登录后查看全文
uswds