无障碍(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 颜色来传达成功/失败,要同时提供文字标签和退出码。
- 编写错误信息时,应当:
- 说明发生了什么,
- 展示如何修复,以及
- 在需要时链接到文档。
- 使用标准的退出码,并确保失败时返回非零值。
终端、日志与仪表盘
- 优先使用平实语言,而非行话。
- 避免使用未加说明的缩写。
- 对严重程度级别(
ERROR、WARN、INFO)使用一致的格式,并在有用时包含时间戳。 - 确保”状态”不是仅通过颜色来传达的。
把无障碍融入贡献流程
当无障碍成为常规流程的一部分时,它会更容易维持下去。
添加 issue 标签和模板
- 创建一个无障碍标签(例如 “accessibility” 或 “a11y”)。
- 创建一个无障碍 issue 模板,包含:
- accessibility 标签
- 预期行为与实际行为
- 复现步骤(可选附带屏幕录制)
- 所用工具(操作系统、浏览器、辅助技术及其版本)
- 用于优先级排序的严重程度分类:
- 严重(Critical): 阻止用户完成核心任务(例如”无法结算”)。
- 高(High): 存在明显困难,但有变通方案。
- 中(Medium): 造成困扰或体验不一致。
- 低(Low): 对可用性影响很小的小问题。
- 如有需要,附上联系方式或升级处理的说明。
可参考这个无障碍 issue 模板示例。
在 Pull Request(PR)中添加无障碍检查清单
对于涉及 UI 改动的项目,可以包含如下问题:
- 键盘导航能否端到端正常工作
- 焦点状态是否可见且符合逻辑
- 表单是否有标签,错误是否会被朗读出来
- 颜色是否不是传达含义的唯一方式
- 是否遵循了”减少动效”的系统设置(如果新增了动画)
- 是否至少检查过一次屏幕阅读器下的行为
可参考这个 PR 模板示例。
明确”完成”的定义
为功能和缺陷修复添加无障碍验收标准,让它不再是可选项或临时补救。
善用 GitHub Copilot
- 创建专门的 Copilot 智能体,将无障碍相关任务自动化融入开发流程,从使用 axe-core 审计页面,到跨版本追踪无障碍改进情况。参考《GitHub Copilot 自定义智能体无障碍入门指南》。
- 根据你的编码风格、无障碍实践和项目背景,定制 Copilot 的建议,确保它们符合你的无障碍要求。参考《使用自定义指令优化 GitHub Copilot 的无障碍表现》指南。
得体而有效地处理无障碍问题报告
无障碍问题往往难以描述、难以复现,并且对报告者能否使用你的项目具有时效性。处理这类报告时:
- 感谢报告者,并不带质疑地提出澄清性问题。
- 优先处理阻断性问题(无法完成核心流程),而不是外观类问题。
- 在可能的情况下提供变通方案。
- 闭环处理:如果报告者愿意,与他们确认修复是否有效。
持续测试无障碍性
自动化工具擅长捕捉回归问题,但只有人工测试才能建立起真正的信心。
自动化检查(擅长捕捉回归)
- 在 UI 代码中进行无障碍相关的 lint 检查。
- 在 CI 中自动扫描常见的 WCAG 违规项(例如使用 GitHub Accessibility Scanner)。
- 编写单元/集成测试,对关键组件断言其 role/name。
人工测试(建立真正信心所必需)
- 纯键盘测试:不用鼠标,能否顺利完成主要流程?
- 屏幕阅读器抽查:
- 缩放与重排:在 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