无障碍(accessibility,常简写为 a11y)意味着不论用户是否残障、使用何种辅助技术、身处何种环境或使用何种设备,都能使用你的项目。它包括但不限于:对屏幕阅读器的支持、纯键盘导航、字幕/文字记录、足够的色彩对比度,以及清晰的内容结构。

与残障人士携手合作

“没有我们的参与,就不要替我们做决定” —— 对无障碍建设而言,最重要的一件事就是把它所服务的人群放在中心位置。有残障经历的用户、贡献者和测试者,能以指南和自动化工具无法企及的方式理解真正的障碍所在。尽早并持续地寻求他们的真实体验。

落到实处

脱离受影响的人群做出的决定,往往会偏离目标。与残障人士一起构建,而不是替他们构建,才能打造出对所有人都更好的软件。

以下是几种纳入真实体验的方式:

  • 邀请残障贡献者参与设计讨论,而不仅仅是缺陷分类(bug triage)。
  • 在条件允许的情况下,邀请残障人士参与可用性测试和反馈。
  • 当有人描述他们如何使用你的项目时,认真倾听,即使这挑战了你原有的假设。
  • 把无障碍报告当作专业意见来对待,而不是抱怨——它们所代表的用户可能比你想象的更多。

无障碍让所有人受益

  • 它影响着大量人群。 根据世界卫生组织的估计,全球约有 13 亿人(六分之一)存在显著的残障情况。
  • 它是质量的一部分。 具备无障碍能力的产品,往往对所有人都更易用。
  • 它降低支持负担。 更清晰的界面和文档意味着更少困惑的用户。
  • 它扩大你的贡献者群体。 辅助技术用户能够更充分地参与进来。
  • 它推动创新。 为多样化需求而设计,往往会带来让所有人都受益的功能(比如字幕、语音控制和深色模式,最初都是无障碍方案)。
  • 它常常是硬性要求。 许多组织(以及一些政府)在采购和合规方面都要求具备无障碍能力。
  • 我们的未来充满不确定性。 没有人能确定自己明天还拥有今天所拥有的能力。

从无障碍声明开始

在动手写代码之前,先花点时间记录下你的项目对无障碍的承诺。一份无障碍声明向用户和贡献者传达了一个信号:无障碍是优先事项,而不是事后补丁。具体做法可参考 W3C 的《撰写无障碍声明》指南

添加一份清晰的声明,设定预期,并让用户能方便地报告问题。你可以直接在 README 中添加一个无障碍章节,也可以创建独立的 ACCESSIBILITY.md 文件,并在 README 中链接到它以提高可见性。可参考这个 ACCESSIBILITY.md 示例

目标

  • 陈述可衡量的目标和准则(在可行的情况下,参考 WCAG AA)。
  • 明确首要优先事项,以及你打算如何实现它们(键盘与屏幕阅读器支持、字幕与文字记录等)。
  • 说明已知的局限性,以及可用的替代方案(如果存在)。

贡献者要求

设立清晰的准则,让贡献者知道项目对他们的期望:

  • 测试: 所有 UI 改动都必须使用无障碍测试工具进行测试(例如 Axe DevTools)。
  • 文档: 针对 SVG、图片、交互元素等组件,遵循项目的无障碍指南。
  • CI/CD: 如果 PR 引入了无障碍检查工作流检测到的违规项,应当让检查失败。

支持的环境

  • 列出你所支持的平台(Web、移动端 Web、iOS、Android、终端/CLI、桌面应用)。
  • 列出任何部分支持的说明。

报告无障碍问题

  • 引导报告者使用无障碍问题模板来创建 issue。
  • 小贴士: 诚实地设定预期(比如”我们正在处理这个问题——进展跟踪见 ISSUE-123”);确认收到报告,并在可能的情况下提供后续进展或临时解决方案。

为什么要把无障碍问题从常规问题流程中独立出来?

用户早已习惯了一份专门的无障碍声明和报告路径——这在私营部门和各类政府网站中都是行之有效的惯例,很多用户在遇到障碍时会首先寻找它。让无障碍问题独立于常规缺陷流程,原因在于:

  • 影响具有时效性。 无障碍缺陷可能导致用户完全无法使用你的项目,而不只是带来不便。独立的报告路径有助于这类问题被更快地分类处理。
  • 上下文不同。 无障碍问题报告需要具体信息(所用辅助技术、操作系统、浏览器、严重程度),而通用的缺陷模板不会主动提示这些内容。
  • 它传达出承诺。 一份可见的、独立的声明向用户和贡献者表明,无障碍是一等公民关切,而不是被塞进”其他缺陷”里草草处理。
  • 报告者本身可能正在使用辅助技术来提交报告。 一个清晰、可预期的流程(固定的文件、固定的标签、固定的模板)能减少受影响最严重的那部分人所面临的阻力。

让文档默认无障碍

文档往往是用户接触到的第一个”界面”。确保每个人都能读懂它。

结构与语义

  • 使用合乎逻辑的标题层级,不要跳级(#####################)。
  • 使用独特且具描述性的链接文字(用”阅读贡献指南”而不是”点击这里”)。
  • 使用平实的语言,避免行话,首次出现的缩写要展开说明。
  • 使用真正的列表,而不是手动打出的编号。
  • 帮助和导航保持在各页面一致的位置,方便用户可预期地找到它们。
  • 避免仅通过位置或样式来传达含义(例如”看右边的红色文字”)。

图片、图表与视频

  • 为图片提供有意义的替代文本(常简称为”alt text”,参考 W3C 的 alt 决策树)。
  • 尽量使用真实文本,而不是文字图片。
  • 对于复杂图片(如架构图),在附近提供额外的文字说明(要点列表或简短解释)。
  • 如果你发布演示、教程、演讲或发布视频:
    • 提供字幕(尽量选择人工校对过的版本)。
    • 提供文字记录
    • 避免自动播放音视频。
    • 用语言描述重要的屏幕操作。

表格

  • 表格只用于呈现表格数据,不要用于页面布局。
  • 提供表头单元格,将列标题和行标题与数据单元格关联起来。
  • 提供说明或摘要,描述表格的用途。

代码块

  • 保持每行长度合理(自动换行有助于可读性)。
  • 不要仅依赖颜色高亮来传达含义。
  • 用文字说明代码做了什么、成功的标志是什么。

设计无障碍的界面

如果你的项目有 Web 界面,以下这些高影响力的默认设计能帮助到所有用户。

键盘支持

  • 所有可交互元素都应能仅通过键盘访问和操作。
  • 确保有可见的焦点指示(除非提供替代方案,否则不要移除焦点轮廓)。
  • 保持与视觉布局一致的、合乎逻辑的 Tab 键顺序
  • 除非你有意管理焦点(例如模态对话框)并提供退出方式,否则不要在组件内困住焦点。

语义优先

  • 尽可能使用原生 HTML 元素(<h1><button><a><input><label>)。
  • 只有在原生 HTML 不够用时才使用 ARIA。没有 ARIA 也好过糟糕的 ARIA。如果确实需要使用,请遵循 ARIA(无障碍富互联网应用)文档,并确保所有可交互的 ARIA 控件都支持键盘操作。
  • 声明文档的语言(例如 HTML 中的 lang="en"),并标注其中语言不同的部分。

名称、标签、说明

  • 每个表单控件都需要关联一个标签
  • 提供清晰的错误信息,指出哪个字段出错,并通过程序化方式(如 aria-describedby)将错误信息与字段关联。
  • 对于必填字段,用文字说明要求(而不只是一个星号)。

颜色与对比度

  • 不要仅用颜色来传达含义(例如”错误是红色的”)。
  • 确保文字、图标和 UI 控件有足够的对比度(参考 WebAIM 的对比度检测工具)。

动效与动画

  • 避免闪烁内容和快速动画。
  • 避免视差效果和自动轮播,或者让它们可以被关闭和控制。
  • 如果操作系统表明用户要求减少或关闭动效,就避免不必要的动画。

动态内容

当内容在不刷新页面的情况下发生更新时,要确保辅助技术用户能够获知:

  • 谨慎地使用合适的 ARIA live region 来发出通知。
  • 在打开/关闭对话框、菜单和抽屉时妥善管理焦点。

依赖与模式

  • 使用有完善无障碍支持文档的组件库。
  • 追踪上游的无障碍缺陷,并在你的 issue 中关联它们。
  • 对自定义 UI 控件保持谨慎。原生控件(如 <button><select><input type="checkbox"><details>)自带浏览器和辅助技术已经理解的键盘支持、焦点管理、屏幕阅读器语义和表单集成能力。在自定义组件中重新实现这些行为既耗时又容易出错,并且会随着平台和辅助技术的演进带来长期维护成本。只有在原生元素确实无法满足需求时,才考虑使用自定义控件。

移动端注意事项

  • 让触控目标至少达到 24×24 CSS 像素
  • 为多指或路径手势(如捏合、滑动)提供单点替代方案。
  • 为拖放操作提供替代方案(按钮、菜单)。
  • 除非内容本身确实需要特定方向,否则不要将内容限制在单一显示方向上。
  • 为由设备运动触发的功能(如摇一摇撤销)提供替代方案。

让工具无障碍

只要设计得当,命令行工具和仪表盘也可以做到高度无障碍。

CLI 工具

命令行应用只要具备可预期性和可脚本化,就能做到高度无障碍。

  • 支持 --help,并提供清晰的用法示例。
  • 为难以解析表格的用户提供机器可读的输出选项(如 --json)。
  • 不要仅依赖 ANSI 颜色来传达成功/失败,要同时提供文字标签和退出码。
  • 编写错误信息时,应当:
    • 说明发生了什么,
    • 展示如何修复,以及
    • 在需要时链接到文档。
  • 使用标准的退出码,并确保失败时返回非零值。

终端、日志与仪表盘

  • 优先使用平实语言,而非行话。
  • 避免使用未加说明的缩写。
  • 对严重程度级别(ERRORWARNINFO)使用一致的格式,并在有用时包含时间戳。
  • 确保”状态”不是仅通过颜色来传达的。

把无障碍融入贡献流程

当无障碍成为常规流程的一部分时,它会更容易维持下去。

添加 issue 标签和模板

  • 创建一个无障碍标签(例如 “accessibility”“a11y”)。
  • 创建一个无障碍 issue 模板,包含:
    • accessibility 标签
    • 预期行为与实际行为
    • 复现步骤(可选附带屏幕录制)
    • 所用工具(操作系统、浏览器、辅助技术及其版本)
    • 用于优先级排序的严重程度分类:
      • 严重(Critical): 阻止用户完成核心任务(例如”无法结算”)。
      • 高(High): 存在明显困难,但有变通方案。
      • 中(Medium): 造成困扰或体验不一致。
      • 低(Low): 对可用性影响很小的小问题。
    • 如有需要,附上联系方式或升级处理的说明。

可参考这个无障碍 issue 模板示例

在 Pull Request(PR)中添加无障碍检查清单

对于涉及 UI 改动的项目,可以包含如下问题:

  • 键盘导航能否端到端正常工作
  • 焦点状态是否可见且符合逻辑
  • 表单是否有标签,错误是否会被朗读出来
  • 颜色是否不是传达含义的唯一方式
  • 是否遵循了”减少动效”的系统设置(如果新增了动画)
  • 是否至少检查过一次屏幕阅读器下的行为

可参考这个 PR 模板示例

明确”完成”的定义

为功能和缺陷修复添加无障碍验收标准,让它不再是可选项或临时补救。

善用 GitHub Copilot

得体而有效地处理无障碍问题报告

无障碍问题往往难以描述、难以复现,并且对报告者能否使用你的项目具有时效性。处理这类报告时:

  • 感谢报告者,并不带质疑地提出澄清性问题。
  • 优先处理阻断性问题(无法完成核心流程),而不是外观类问题。
  • 在可能的情况下提供变通方案。
  • 闭环处理:如果报告者愿意,与他们确认修复是否有效。

持续测试无障碍性

自动化工具擅长捕捉回归问题,但只有人工测试才能建立起真正的信心。

自动化检查(擅长捕捉回归)

  • 在 UI 代码中进行无障碍相关的 lint 检查。
  • 在 CI 中自动扫描常见的 WCAG 违规项(例如使用 GitHub Accessibility Scanner)。
  • 编写单元/集成测试,对关键组件断言其 role/name

人工测试(建立真正信心所必需)

  • 纯键盘测试:不用鼠标,能否顺利完成主要流程?
  • 屏幕阅读器抽查:
    • macOS:VoiceOver
    • Windows:NVDA(在开源社区中常用)、JAWS(企业场景常用)
  • 缩放与重排:在 200% 缩放和窄屏宽度下测试。
  • 在适用的情况下测试高对比度/强制颜色模式。

小贴士: 在发布检查清单中加入一个轻量的”无障碍冒烟测试“环节。

本周就能开始的一些小改进

你不需要一次做完所有事,可以先从几个能快速见效的改进入手。

挑几项来做:

  • 添加 ACCESSIBILITY.md 文件,并创建一个无障碍标签(如 “accessibility”“a11y”
  • 确保每个可交互元素都能通过键盘访问
  • 修复缺失的表单标签
  • 声明文档的语言(例如 HTML 中的 lang="en"),并标注其中语言不同的部分
  • 为 README 和文档添加替代文本和标题结构
  • 在 PR 检查清单中加入键盘/焦点相关条目
  • 为你最受欢迎的视频添加字幕/文字记录
  • 为某个 CLI 命令添加 --json 输出

有助于将无障碍承诺正式落地的建议文件

可以考虑在你的仓库中添加以下文件:

  • ACCESSIBILITY.md:你的无障碍声明、问题报告方式,以及任何项目特定的指导(组件规则、模式、已知问题)——ACCESSIBILITY.md 示例
  • .github/ISSUE_TEMPLATE/accessibility.yml:无障碍缺陷报告模板——无障碍 issue 模板示例
  • .github/pull_request_template.md:包含无障碍检查清单——PR 模板示例

可参考这个提供了更多示例的项目

结语:你的一小步,用户体验的一大步

这些步骤看起来可能很基础,但它们能大幅提升项目的无障碍程度。你所做的每一个修复——无论是补上一个缺失的标签、消除一个键盘焦点陷阱,还是为视频加上字幕——都会为一位此前无法使用你项目的用户打开一扇门。

无障碍不是一次性的修复,而是一项持续的实践,你不需要一次性做完所有事情。从键盘导航和语义结构开始,保持改动小步进行,并尽早寻求评审。

你今天投入的这些努力,意味着会有更多人能够从你构建的成果中学习、为之贡献,并依赖它。这份收获值得庆祝。

贡献者

非常感谢所有为本指南分享经验和建议的维护者!

本指南由 @mlama007 撰写,并有以下贡献者参与:@ericwbailey@andyfeller@mgifford@smockle@weboverhauls