|
| 1 | +--- |
| 2 | +lang: zh-hans |
| 3 | +title: 项目无障碍最佳实践 |
| 4 | +description: 让你的开源项目对所有人(尤其是残障人士)可用的实用、可落地的步骤。 |
| 5 | +class: accessibility-best-practices |
| 6 | +order: -1 |
| 7 | +image: /assets/images/cards/accessibility-best-practices.png |
| 8 | +--- |
| 9 | + |
| 10 | +无障碍(accessibility,常简写为 _a11y_)意味着不论用户是否残障、使用何种辅助技术、身处何种环境或使用何种设备,都能使用你的项目。它包括但不限于:对屏幕阅读器的支持、纯键盘导航、字幕/文字记录、足够的色彩对比度,以及清晰的内容结构。 |
| 11 | + |
| 12 | +## 与残障人士携手合作 |
| 13 | + |
| 14 | +**"没有我们的参与,就不要替我们做决定"** —— 对无障碍建设而言,最重要的一件事就是把它所服务的人群放在中心位置。有残障经历的用户、贡献者和测试者,能以指南和自动化工具无法企及的方式理解真正的障碍所在。尽早并持续地寻求他们的真实体验。 |
| 15 | + |
| 16 | +### 落到实处 |
| 17 | + |
| 18 | +脱离受影响的人群做出的决定,往往会偏离目标。与残障人士一起构建,而不是替他们构建,才能打造出对所有人都更好的软件。 |
| 19 | + |
| 20 | +以下是几种纳入真实体验的方式: |
| 21 | + |
| 22 | +* 邀请残障贡献者参与设计讨论,而不仅仅是缺陷分类(bug triage)。 |
| 23 | +* 在条件允许的情况下,邀请残障人士参与可用性测试和反馈。 |
| 24 | +* 当有人描述他们如何使用你的项目时,认真倾听,即使这挑战了你原有的假设。 |
| 25 | +* 把无障碍报告当作专业意见来对待,而不是抱怨——它们所代表的用户可能比你想象的更多。 |
| 26 | + |
| 27 | +### 无障碍让所有人受益 |
| 28 | + |
| 29 | +* **它影响着大量人群。** 根据[世界卫生组织](https://www.who.int/news-room/fact-sheets/detail/disability-and-health)的估计,全球约有 13 亿人(六分之一)存在显著的残障情况。 |
| 30 | +* **它是质量的一部分。** 具备无障碍能力的产品,往往对所有人都更易用。 |
| 31 | +* **它降低支持负担。** 更清晰的界面和文档意味着更少困惑的用户。 |
| 32 | +* **它扩大你的贡献者群体。** 辅助技术用户能够更充分地参与进来。 |
| 33 | +* **它推动创新。** 为多样化需求而设计,往往会带来让所有人都受益的功能(比如字幕、语音控制和深色模式,最初都是无障碍方案)。 |
| 34 | +* **它常常是硬性要求。** 许多组织(以及一些政府)在采购和合规方面都要求具备无障碍能力。 |
| 35 | +* **我们的未来充满不确定性。** 没有人能确定自己明天还拥有今天所拥有的能力。 |
| 36 | + |
| 37 | +## 从无障碍声明开始 |
| 38 | + |
| 39 | +在动手写代码之前,先花点时间记录下你的项目对无障碍的承诺。一份无障碍声明向用户和贡献者传达了一个信号:无障碍是优先事项,而不是事后补丁。具体做法可参考 [W3C 的《撰写无障碍声明》指南](https://www.w3.org/WAI/planning/statements/)。 |
| 40 | + |
| 41 | +添加一份清晰的声明,设定预期,并让用户能方便地报告问题。你可以直接在 README 中添加一个无障碍章节,也可以创建独立的 **ACCESSIBILITY.md** 文件,并在 README 中链接到它以提高可见性。可参考这个 [ACCESSIBILITY.md 示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/ACCESSIBILITY.md)。 |
| 42 | + |
| 43 | +### 目标 |
| 44 | + |
| 45 | +* 陈述可衡量的目标和准则(在可行的情况下,参考 [WCAG AA](https://www.w3.org/TR/WCAG22/#wcag-2-layers-of-guidance))。 |
| 46 | +* 明确首要优先事项,以及你打算如何实现它们(键盘与屏幕阅读器支持、字幕与文字记录等)。 |
| 47 | +* 说明已知的局限性,以及可用的替代方案(如果存在)。 |
| 48 | + |
| 49 | +### 贡献者要求 |
| 50 | + |
| 51 | +设立清晰的准则,让贡献者知道项目对他们的期望: |
| 52 | + |
| 53 | +* **测试:** 所有 UI 改动都必须使用无障碍测试工具进行测试(例如 [Axe DevTools](https://www.deque.com/axe/devtools/extension/#:~:text=Try%20Axe%20DevTools%20Extension%20in%20your%20browser%20of%20choice))。 |
| 54 | +* **文档:** 针对 SVG、图片、交互元素等组件,遵循项目的无障碍指南。 |
| 55 | +* **CI/CD:** 如果 PR 引入了无障碍检查工作流检测到的违规项,应当让检查失败。 |
| 56 | + |
| 57 | +### 支持的环境 |
| 58 | + |
| 59 | +* 列出你所支持的平台(Web、移动端 Web、iOS、Android、终端/CLI、桌面应用)。 |
| 60 | +* 列出任何部分支持的说明。 |
| 61 | + |
| 62 | +### 报告无障碍问题 |
| 63 | + |
| 64 | +* 引导报告者使用无障碍问题模板来创建 issue。 |
| 65 | +* **小贴士:** 诚实地设定预期(比如"我们正在处理这个问题——进展跟踪见 ISSUE-123");确认收到报告,并在可能的情况下提供后续进展或临时解决方案。 |
| 66 | + |
| 67 | +#### 为什么要把无障碍问题从常规问题流程中独立出来? |
| 68 | + |
| 69 | +用户早已习惯了一份专门的无障碍声明和报告路径——这在私营部门和各类政府网站中都是行之有效的惯例,很多用户在遇到障碍时会首先寻找它。让无障碍问题独立于常规缺陷流程,原因在于: |
| 70 | + |
| 71 | +* **影响具有时效性。** 无障碍缺陷可能导致用户完全无法使用你的项目,而不只是带来不便。独立的报告路径有助于这类问题被更快地分类处理。 |
| 72 | +* **上下文不同。** 无障碍问题报告需要具体信息(所用辅助技术、操作系统、浏览器、严重程度),而通用的缺陷模板不会主动提示这些内容。 |
| 73 | +* **它传达出承诺。** 一份可见的、独立的声明向用户和贡献者表明,无障碍是一等公民关切,而不是被塞进"其他缺陷"里草草处理。 |
| 74 | +* **报告者本身可能正在使用辅助技术来提交报告。** 一个清晰、可预期的流程(固定的文件、固定的标签、固定的模板)能减少受影响最严重的那部分人所面临的阻力。 |
| 75 | + |
| 76 | +## 让文档默认无障碍 |
| 77 | + |
| 78 | +文档往往是用户接触到的第一个"界面"。确保每个人都能读懂它。 |
| 79 | + |
| 80 | +### 结构与语义 |
| 81 | + |
| 82 | +* 使用**合乎逻辑的标题层级**,不要跳级(`#`、`##`、`###`、`####`、`#####`、`######`)。 |
| 83 | +* 使用**独特且具描述性的链接文字**(用"阅读贡献指南"而不是"点击这里")。 |
| 84 | +* 使用平实的语言,避免行话,首次出现的缩写要展开说明。 |
| 85 | +* [使用**真正的列表**](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#lists),而不是手动打出的编号。 |
| 86 | +* 让**帮助和导航保持在各页面一致的位置**,方便用户可预期地找到它们。 |
| 87 | +* 避免仅通过位置或样式来传达含义(例如"看右边的红色文字")。 |
| 88 | + |
| 89 | +### 图片、图表与视频 |
| 90 | + |
| 91 | +* 为图片提供有意义的**替代文本**(常简称为"alt text",参考 [W3C 的 alt 决策树](https://www.w3.org/WAI/tutorials/images/decision-tree/))。 |
| 92 | +* 尽量使用真实文本,而不是文字图片。 |
| 93 | +* 对于复杂图片(如架构图),在附近提供额外的**文字说明**(要点列表或简短解释)。 |
| 94 | +* 如果你发布演示、教程、演讲或发布视频: |
| 95 | + * 提供**字幕**(尽量选择人工校对过的版本)。 |
| 96 | + * 提供**文字记录**。 |
| 97 | + * 避免自动播放音视频。 |
| 98 | + * 用语言描述重要的屏幕操作。 |
| 99 | + |
| 100 | +### 表格 |
| 101 | + |
| 102 | +* 表格只用于呈现表格数据,不要用于页面布局。 |
| 103 | +* 提供**表头单元格**,将列标题和行标题与数据单元格关联起来。 |
| 104 | +* 提供**说明或摘要**,描述表格的用途。 |
| 105 | + |
| 106 | +### 代码块 |
| 107 | + |
| 108 | +* 保持每行长度合理(自动换行有助于可读性)。 |
| 109 | +* 不要仅依赖颜色高亮来传达含义。 |
| 110 | +* 用文字说明代码做了什么、成功的标志是什么。 |
| 111 | + |
| 112 | +## 设计无障碍的界面 |
| 113 | + |
| 114 | +如果你的项目有 Web 界面,以下这些高影响力的默认设计能帮助到所有用户。 |
| 115 | + |
| 116 | +### 键盘支持 |
| 117 | + |
| 118 | +* 所有可交互元素都应能**仅通过键盘**访问和操作。 |
| 119 | +* 确保有**可见的焦点指示**(除非提供替代方案,否则不要移除焦点轮廓)。 |
| 120 | +* 保持与视觉布局一致的、合乎逻辑的 **Tab 键顺序**。 |
| 121 | +* 除非你有意管理焦点(例如模态对话框)并提供退出方式,否则不要在组件内困住焦点。 |
| 122 | + |
| 123 | +### 语义优先 |
| 124 | + |
| 125 | +* 尽可能使用**原生 HTML** 元素(`<h1>`、`<button>`、`<a>`、`<input>`、`<label>`)。 |
| 126 | +* 只有在原生 HTML 不够用时才使用 **ARIA**。没有 ARIA 也好过糟糕的 ARIA。如果确实需要使用,请遵循 [ARIA(无障碍富互联网应用)文档](https://www.w3.org/TR/wai-aria/),并确保所有可交互的 ARIA 控件都支持键盘操作。 |
| 127 | +* 声明文档的**语言**(例如 HTML 中的 `lang="en"`),并标注其中语言不同的部分。 |
| 128 | + |
| 129 | +### 名称、标签、说明 |
| 130 | + |
| 131 | +* 每个表单控件都需要关联一个**标签**。 |
| 132 | +* 提供**清晰的错误信息**,指出哪个字段出错,并通过程序化方式(如 `aria-describedby`)将错误信息与字段关联。 |
| 133 | +* 对于必填字段,用文字说明要求(而不只是一个星号)。 |
| 134 | + |
| 135 | +### 颜色与对比度 |
| 136 | + |
| 137 | +* 不要仅用颜色来传达含义(例如"错误是红色的")。 |
| 138 | +* 确保文字、图标和 UI 控件有足够的对比度(参考 [WebAIM 的对比度检测工具](https://webaim.org/resources/contrastchecker/))。 |
| 139 | + |
| 140 | +### 动效与动画 |
| 141 | + |
| 142 | +* 避免闪烁内容和快速动画。 |
| 143 | +* 避免视差效果和自动轮播,或者让它们可以被关闭和控制。 |
| 144 | +* 如果操作系统表明用户要求减少或关闭动效,就避免不必要的动画。 |
| 145 | + |
| 146 | +### 动态内容 |
| 147 | + |
| 148 | +当内容在不刷新页面的情况下发生更新时,要确保辅助技术用户能够获知: |
| 149 | + |
| 150 | +* 谨慎地使用合适的 **ARIA live region** 来发出通知。 |
| 151 | +* 在打开/关闭对话框、菜单和抽屉时妥善管理焦点。 |
| 152 | + |
| 153 | +### 依赖与模式 |
| 154 | + |
| 155 | +* 使用有完善无障碍支持文档的组件库。 |
| 156 | +* 追踪上游的无障碍缺陷,并在你的 issue 中关联它们。 |
| 157 | +* 对自定义 UI 控件保持谨慎。原生控件(如 `<button>`、`<select>`、`<input type="checkbox">`、`<details>`)自带浏览器和辅助技术已经理解的键盘支持、焦点管理、屏幕阅读器语义和表单集成能力。在自定义组件中重新实现这些行为既耗时又容易出错,并且会随着平台和辅助技术的演进带来长期维护成本。只有在原生元素确实无法满足需求时,才考虑使用自定义控件。 |
| 158 | + |
| 159 | +### 移动端注意事项 |
| 160 | + |
| 161 | +* 让触控目标至少达到 **24×24 CSS 像素**。 |
| 162 | +* 为多指或路径手势(如捏合、滑动)提供单点替代方案。 |
| 163 | +* 为拖放操作提供替代方案(按钮、菜单)。 |
| 164 | +* 除非内容本身确实需要特定方向,否则不要将内容限制在单一显示方向上。 |
| 165 | +* 为由设备运动触发的功能(如摇一摇撤销)提供替代方案。 |
| 166 | + |
| 167 | +## 让工具无障碍 |
| 168 | + |
| 169 | +只要设计得当,命令行工具和仪表盘也可以做到高度无障碍。 |
| 170 | + |
| 171 | +### CLI 工具 |
| 172 | + |
| 173 | +命令行应用只要具备可预期性和可脚本化,就能做到高度无障碍。 |
| 174 | + |
| 175 | +* 支持 `--help`,并提供清晰的用法示例。 |
| 176 | +* 为难以解析表格的用户提供**机器可读的输出**选项(如 `--json`)。 |
| 177 | +* 不要仅依赖 ANSI 颜色来传达成功/失败,要同时提供文字标签和退出码。 |
| 178 | +* 编写错误信息时,应当: |
| 179 | + * 说明发生了什么, |
| 180 | + * 展示如何修复,以及 |
| 181 | + * 在需要时链接到文档。 |
| 182 | +* 使用标准的退出码,并确保失败时返回非零值。 |
| 183 | + |
| 184 | +### 终端、日志与仪表盘 |
| 185 | + |
| 186 | +* 优先使用平实语言,而非行话。 |
| 187 | +* 避免使用未加说明的缩写。 |
| 188 | +* 对严重程度级别(`ERROR`、`WARN`、`INFO`)使用一致的格式,并在有用时包含时间戳。 |
| 189 | +* 确保"状态"不是仅通过颜色来传达的。 |
| 190 | + |
| 191 | +## 把无障碍融入贡献流程 |
| 192 | + |
| 193 | +当无障碍成为常规流程的一部分时,它会更容易维持下去。 |
| 194 | + |
| 195 | +### 添加 issue 标签和模板 |
| 196 | + |
| 197 | +* 创建一个无障碍标签(例如 _"accessibility"_ 或 _"a11y"_)。 |
| 198 | +* 创建一个无障碍 issue 模板,包含: |
| 199 | + * _accessibility_ 标签 |
| 200 | + * 预期行为与实际行为 |
| 201 | + * 复现步骤(可选附带屏幕录制) |
| 202 | + * 所用工具(操作系统、浏览器、辅助技术及其版本) |
| 203 | + * 用于优先级排序的严重程度分类: |
| 204 | + * **严重(Critical):** 阻止用户完成核心任务(例如"无法结算")。 |
| 205 | + * **高(High):** 存在明显困难,但有变通方案。 |
| 206 | + * **中(Medium):** 造成困扰或体验不一致。 |
| 207 | + * **低(Low):** 对可用性影响很小的小问题。 |
| 208 | + * 如有需要,附上联系方式或升级处理的说明。 |
| 209 | + |
| 210 | +可参考这个[无障碍 issue 模板示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/.github/ISSUE_TEMPLATE/accessibility.yml)。 |
| 211 | + |
| 212 | +### 在 Pull Request(PR)中添加无障碍检查清单 |
| 213 | + |
| 214 | +对于涉及 UI 改动的项目,可以包含如下问题: |
| 215 | + |
| 216 | +* 键盘导航能否端到端正常工作 |
| 217 | +* 焦点状态是否可见且符合逻辑 |
| 218 | +* 表单是否有标签,错误是否会被朗读出来 |
| 219 | +* 颜色是否不是传达含义的唯一方式 |
| 220 | +* 是否遵循了"减少动效"的系统设置(如果新增了动画) |
| 221 | +* 是否至少检查过一次屏幕阅读器下的行为 |
| 222 | + |
| 223 | +可参考这个 [PR 模板示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/.github/PULL_REQUEST_TEMPLATE.md)。 |
| 224 | + |
| 225 | +### 明确"完成"的定义 |
| 226 | + |
| 227 | +为功能和缺陷修复添加无障碍验收标准,让它不再是可选项或临时补救。 |
| 228 | + |
| 229 | +### 善用 GitHub Copilot |
| 230 | + |
| 231 | +* 创建专门的 Copilot 智能体,将无障碍相关任务自动化融入开发流程,从使用 [axe-core](https://github.com/dequelabs/axe-core) 审计页面,到跨版本追踪无障碍改进情况。参考[《GitHub Copilot 自定义智能体无障碍入门指南》](https://accessibility.github.com/documentation/guide/getting-started-with-agents/)。 |
| 232 | +* 根据你的编码风格、无障碍实践和项目背景,定制 Copilot 的建议,确保它们符合你的无障碍要求。参考[《使用自定义指令优化 GitHub Copilot 的无障碍表现》指南](https://accessibility.github.com/documentation/guide/copilot-instructions/)。 |
| 233 | + |
| 234 | +### 得体而有效地处理无障碍问题报告 |
| 235 | + |
| 236 | +无障碍问题往往难以描述、难以复现,并且对报告者能否使用你的项目具有时效性。处理这类报告时: |
| 237 | + |
| 238 | +* 感谢报告者,并不带质疑地提出澄清性问题。 |
| 239 | +* 优先处理阻断性问题(无法完成核心流程),而不是外观类问题。 |
| 240 | +* 在可能的情况下提供变通方案。 |
| 241 | +* 闭环处理:如果报告者愿意,与他们确认修复是否有效。 |
| 242 | + |
| 243 | +## 持续测试无障碍性 |
| 244 | + |
| 245 | +自动化工具擅长捕捉回归问题,但只有人工测试才能建立起真正的信心。 |
| 246 | + |
| 247 | +### 自动化检查(擅长捕捉回归) |
| 248 | + |
| 249 | +* 在 UI 代码中进行无障碍相关的 lint 检查。 |
| 250 | +* 在 CI 中自动扫描常见的 WCAG 违规项(例如使用 [GitHub Accessibility Scanner](https://github.com/github/accessibility-scanner))。 |
| 251 | +* 编写单元/集成测试,对关键组件断言其 [role/name](https://www.w3.org/TR/accname-1.2/)。 |
| 252 | + |
| 253 | +### 人工测试(建立真正信心所必需) |
| 254 | + |
| 255 | +* **纯键盘**测试:不用鼠标,能否顺利完成主要流程? |
| 256 | +* **屏幕阅读器**抽查: |
| 257 | + * macOS:[VoiceOver](https://support.apple.com/guide/voiceover/welcome/mac) |
| 258 | + * Windows:[NVDA](https://www.nvaccess.org/about-nvda/)(在开源社区中常用)、[JAWS](https://vispero.com/jaws-screen-reader-software/)(企业场景常用) |
| 259 | +* **缩放与重排**:在 200% 缩放和窄屏宽度下测试。 |
| 260 | +* 在适用的情况下测试**高对比度/强制颜色**模式。 |
| 261 | + |
| 262 | +**小贴士:** 在发布检查清单中加入一个轻量的"无障碍[冒烟测试](https://en.wikipedia.org/wiki/Smoke_testing_(software))"环节。 |
| 263 | + |
| 264 | +## 本周就能开始的一些小改进 |
| 265 | + |
| 266 | +### 你不需要一次做完所有事,可以先从几个能快速见效的改进入手。 |
| 267 | + |
| 268 | +挑几项来做: |
| 269 | + |
| 270 | +* 添加 `ACCESSIBILITY.md` 文件,并创建一个无障碍标签(如 _"accessibility"_ 或 _"a11y"_) |
| 271 | +* 确保每个可交互元素都能通过键盘访问 |
| 272 | +* 修复缺失的表单标签 |
| 273 | +* 声明文档的**语言**(例如 HTML 中的 `lang="en"`),并标注其中语言不同的部分 |
| 274 | +* 为 README 和文档添加替代文本和标题结构 |
| 275 | +* 在 PR 检查清单中加入键盘/焦点相关条目 |
| 276 | +* 为你最受欢迎的视频添加字幕/文字记录 |
| 277 | +* 为某个 CLI 命令添加 `--json` 输出 |
| 278 | + |
| 279 | +### 有助于将无障碍承诺正式落地的建议文件 |
| 280 | + |
| 281 | +可以考虑在你的仓库中添加以下文件: |
| 282 | + |
| 283 | +* `ACCESSIBILITY.md`:你的无障碍声明、问题报告方式,以及任何项目特定的指导(组件规则、模式、已知问题)——[ACCESSIBILITY.md 示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/ACCESSIBILITY.md) |
| 284 | +* `.github/ISSUE_TEMPLATE/accessibility.yml`:无障碍缺陷报告模板——[无障碍 issue 模板示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/.github/ISSUE_TEMPLATE/accessibility.yml) |
| 285 | +* `.github/pull_request_template.md`:包含无障碍检查清单——[PR 模板示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/.github/PULL_REQUEST_TEMPLATE.md) |
| 286 | + |
| 287 | +可参考这个[提供了更多示例的项目](https://github.com/mgifford/ACCESSIBILITY.md/tree/main)。 |
| 288 | + |
| 289 | +## 结语:你的一小步,用户体验的一大步 |
| 290 | + |
| 291 | +这些步骤看起来可能很基础,但它们能大幅提升项目的无障碍程度。你所做的每一个修复——无论是补上一个缺失的标签、消除一个键盘焦点陷阱,还是为视频加上字幕——都会为一位此前无法使用你项目的用户打开一扇门。 |
| 292 | + |
| 293 | +无障碍不是一次性的修复,而是一项持续的实践,你不需要一次性做完所有事情。从键盘导航和语义结构开始,保持改动小步进行,并尽早寻求评审。 |
| 294 | + |
| 295 | +你今天投入的这些努力,意味着会有更多人能够从你构建的成果中学习、为之贡献,并依赖它。这份收获值得庆祝。 |
| 296 | + |
| 297 | +## 贡献者 |
| 298 | + |
| 299 | +### 非常感谢所有为本指南分享经验和建议的维护者! |
| 300 | + |
| 301 | +本指南由 [@mlama007](https://github.com/mlama007) 撰写,并有以下贡献者参与:[@ericwbailey](https://github.com/ericwbailey)、[@andyfeller](https://github.com/andyfeller)、[@mgifford](https://github.com/mgifford)、[@smockle](https://github.com/smockle) 和 [@weboverhauls](https://github.com/weboverhauls) |
0 commit comments