面向 Web 开发者的无障碍功能

改进无障碍功能可让您的网站对所有人来说都更便于使用。

Addy Osmani
Addy Osmani

请务必构建包容且人人都可访问的网站。 你可以针对至少六个关键的残疾领域进行优化:视觉、听力、行动能力、认知、言语和神经系统。即使您是刚开始接触 Web 无障碍功能,这里的许多工具和资源也很有用。

超过 10 亿人患有某种形式的残疾。

为了让用户能够访问该网站,网站需要能够在具有不同屏幕尺寸和类型输入内容(例如屏幕阅读器)的多台设备上正常运行。此外,网站应该可供最广泛的用户(包括残障用户)使用。

以下是用户可能存在的一些残疾:

视觉 听力 行动不便
  • 低视力
  • 盲人
  • 色盲
  • 白内障
  • 防晒
  • 听障
  • 失聪
  • 噪音
  • 耳部感染
  • 脊髓受伤
  • 灵敏度有限
  • 双手处于忙碌状态
认知 语音 神经
  • 学习障碍
  • 困倦或分心
  • 偏头痛
  • 孤独症
  • 发作
  • 环境噪声
  • 喉咙痛
  • 语言障碍
  • 无法说话
  • 忧郁症
  • 创伤后应激障碍 (PTSD)
  • 躁郁症
  • 焦虑

视觉问题的范围很广,例如无法辨别颜色,到完全看不到视力。

  • 确保文本内容达到最低对比度阈值
  • 避免仅使用颜色来传达信息,并确保所有文本都resizable
  • 确保所有界面组件都可以与辅助技术(例如屏幕阅读器、放大镜和盲文显示屏)搭配使用。这其中包括确保标记界面组件,以便无障碍功能 API 能够以程序化方式确定任何元素的 rolestatevaluetitle

Chrome 开发者工具“检查元素”提示的屏幕截图。

我个人的视力不佳,经常需要放大网站、开发者工具和终端。 虽然支持缩放几乎永远不会出现在开发者的待办事项列表头部,但它可以给像我这样的用户带来很大的不同。

听力问题表示用户可能无法听见网页上发出的声音。

ChromeVox 屏幕阅读器朗读网页的屏幕截图。

移动性问题可能包括无法使用鼠标、键盘或触摸屏。

  • 对于原本使用鼠标执行的任何操作,应使界面组件的内容可通过键盘功能访问
  • 确保已针对通常使用相同的 API 的辅助技术(包括屏幕阅读器、语音控制软件和实体开关控制)正确标记页面。

认知问题意味着用户可能需要辅助技术来帮助他们阅读文本,因此请务必确保存在替代文本。

  • 使用动画时要小心。避免使用重复或闪烁的视频和动画,因为这可能会导致某些用户遇到问题

    借助 prefers-reduced-motion CSS 媒体查询,您可以为喜欢减少动作的用户限制动画和自动播放的视频:

    /*
    If the user expresses a preference for reduced motion, don't use animations on buttons.
    */
    @media (prefers-reduced-motion: reduce) {
      button {
        animation: none;
      }
    }
    
  • 避免基于时间的互动。

这似乎有很多内容需要涵盖的基础,但我们将介绍评估和改进界面组件无障碍功能的流程。

为了提供额外的视觉支持,GOV.UK 无障碍团队制作了一系列无障碍功能正确做法和错误做法的数字海报,您可以利用它们与团队分享最佳实践。

展示无障碍功能正确做法和错误做法的数字海报。
六张海报,其中列出了无障碍功能最佳实践。阅读全文

衡量界面组件的无障碍功能

审核网页界面组件的无障碍功能时,请思考以下问题:

  • 您是否可以只通过键盘使用界面组件?

    该组件是否管理焦点并避免焦点陷阱? 它能否响应相应的键盘事件?

  • 您可以搭配屏幕阅读器使用界面组件吗?

    对于视觉呈现的信息,您是否提供了替代文字? 您是否使用 ARIA 添加了语义信息?

  • 界面组件能否在静音状态下运行?

    关闭扬声器并检查用例。

  • 界面组件能否在没有颜色的情况下工作?

    确保您的界面组件可供看不见颜色的用户使用。名为 Colorblindly 的 Chrome 扩展程序是一款非常实用的模拟色盲工具。(尝试所有四种形式的色盲模拟功能。) 您可能还会对 Daltonize 扩展程序感兴趣,该扩展程序同样很有用。

  • 您的界面组件能否在启用高对比度模式的情况下使用?

    所有现代操作系统都支持高对比度模式。高对比度是 Chrome 扩展程序,可以为您提供帮助。

标准化控件(例如 <button><select>)在浏览器中内置了无障碍功能。它们可使用 Tab 键获得焦点;它们会响应键盘事件(如 EnterSpace 和箭头键);并且它们具有无障碍工具使用的语义角色、状态和属性。默认样式还应符合所列的无障碍要求。

自定义界面组件(扩展 <button> 等标准元素的组件除外)没有任何内置功能(包括无障碍功能),因此您需要提供该功能。实现无障碍功能时,最好先将您的组件与类似的标准元素(或多个标准元素的组合,具体取决于组件的复杂程度)进行比较。

大多数浏览器开发者工具都支持检查网页的无障碍树。在 Chrome 开发者工具中,您可以在元素面板的无障碍标签页中找到此选项。

Chrome 开发者工具中的无障碍功能树状视图的屏幕截图。

Firefox 还有一个无障碍面板。

FireFox 开发者工具中无障碍功能树状视图的屏幕截图。

Safari 会在元素面板的节点标签中显示无障碍功能信息。

您在尝试使界面组件使用起来更没有障碍时,可以问问自己以下问题列表。

改善键盘焦点

理想情况下,应确保界面组件中的所有功能都可以使用键盘进行访问。在设计用户体验时,请考虑如何只使用键盘来使用元素,并确定一组一致的键盘互动方式。

首先,确保为每个组件设置合理的焦点目标。例如,菜单等复杂组件可能是页面内的一个焦点目标,但之后应在其自身内管理焦点,以便活动菜单项始终获得焦点。

需要焦点管理的菜单和子菜单的屏幕截图。
管理复杂元素中的焦点。

使用 tabindex

您可以使用 tabindex 属性为元素和界面组件添加键盘焦点。仅使用键盘和辅助技术的用户需要能够将键盘焦点放在元素上以与它们互动。

内置互动元素(如 <button>)隐式可聚焦,因此它们不需要 tabindex 属性,除非您需要在 Tab 键顺序中更改这些元素的位置。

tabindex 值有三种类型:

  • tabindex="0" 是最常使用的方法,并按自然 Tab 键顺序(由 DOM 顺序定义)放置元素。
  • 如果 tabindex 值大于 0,则系统会按照手动 Tab 键顺序来放置元素。系统会按数字顺序访问网页中所有值为正数的元素,即按自然 Tab 键顺序排列的元素之前。tabindex
  • 如果 tabindex 值等于 -1,则该元素可以编程方式聚焦,但不按 Tab 键顺序进行聚焦。

对于自定义界面组件,请始终将 tabindex 值设为 0 或 -1,因为您将无法提前确定给定页面上元素的顺序。tabindex 值为 -1 特别适用于管理复杂组件中的焦点。

无论是使用默认焦点环样式,还是应用可识别的自定义焦点样式,确保焦点始终可见。切记不要让键盘用户陷入困境,因为他们应该能够只使用键盘就能将焦点从元素移开。

使用自动对焦功能

借助 HTML autofocus 属性,作者可以指定特定元素应在页面加载时自动获得焦点。 所有网络表单控件(包括按钮)均已支持 autofocus。如需自动聚焦您自己的自定义界面组件中的元素,请调用 focus() 方法,所有可聚焦的 HTML 元素(例如 document.querySelector('myButton').focus())均支持该方法。

添加键盘互动方式

界面组件可聚焦后,请通过处理适当的键盘事件在组件获得焦点时提供良好的键盘互动故事。例如,允许用户使用箭头键选择菜单选项,并使用 SpaceEnter 激活按钮。ARIA 设计模式指南在此处提供了一些指导。

最后,确保您的键盘快捷键易于发现。 常见做法是使用键盘快捷键图例(屏幕上的文字)来告知用户存在快捷键。例如,“按 ?键盘快捷键”或者,也可以使用提示等提示来告知用户快捷方式。

管理焦点的重要性怎么强调都不为过。一个重要的示例是抽屉式导航栏。如果您向页面中添加界面组件,则需要将焦点转到该页面中的某个元素;否则,用户可能需要在整个页面中按 Tab 键才能转到该页面。这可能会令人不快,因此请务必测试网页中所有键盘可导航组件的焦点。

WalkMe 状态切换测试。
// Example for expanding and collapsing a category with the Space key
const category = await page.$(`.category`);

// verify tabIndex, role and focus
expect(await page.evaluate(elem => elem.getAttribute(`role`), category)).toEqual(`button`);
expect(await page.evaluate(elem => elem.getAttribute(`tabindex`), category)).toEqual(`0`);
expect(await page.evaluate(elem => window.document.activeElement === elem, category)).toEqual(true);

// verify aria-expanded = false
expect(await page.evaluate(elem => elem.getAttribute(`aria-expanded`), category)).toEqual(`false`);

// toggle category by pressing Space
await page.keyboard.press('Space');

// verify aria-expanded = true
expect(await page.evaluate(elem => elem.getAttribute(`aria-expanded`), category)).toEqual(`true`);

确保屏幕阅读器能正常使用

大约 1% 到 2% 的用户使用屏幕阅读器。您能否只使用屏幕阅读器和键盘了解所有重要信息并与该组件互动?

以下问题可帮助您了解屏幕阅读器的无障碍功能。

是否所有组件和图片都有有意义的替代文本?

在通过直观方式传达互动组件名称用途的相关信息时,应提供易于访问的文本替代文本。

例如,如果您的 <fancy-menu> 界面组件仅显示一个齿轮图标来表明这是设置菜单,则需要提供一个无障碍文本替代文本,例如“设置”来传达相同的信息。 根据上下文,您可以在 Shadow DOM 中使用 alt 属性、aria-label 属性、aria-labelledby 属性或纯文本提供替代文本。 您可以在 WebAIM 快速参考中找到常规技术提示。

显示图片的任何界面组件都应提供一种机制,用于为图片提供替代文本,类似于 alt 属性。

您的组件是否提供语义信息?

辅助技术可以传达语义信息,而这些信息可以通过格式、光标样式或位置等视觉提示传达给视力正常的用户。标准化元素具有浏览器内置的这种语义信息,但对于自定义组件,您需要使用 ARIA 来添加该信息。

一般来说,任何监听鼠标点击或悬停事件的组件都应具有某种键盘事件监听器和 ARIA 角色,可能还包括 ARIA 状态和属性。

例如,自定义 <fancy-slider> 界面组件可能充当滑块的 ARIA 角色,它具有一些相关的 ARIA 属性:aria-valuenowaria-valueminaria-valuemax。通过将这些属性绑定到自定义组件上的相关属性,您可以允许辅助技术用户与元素互动、更改其值,甚至使元素的视觉呈现效果相应地发生变化。

滑块的屏幕截图。
范围滑块组件。
<fancy-slider role="slider" aria-valuemin="1" aria-valuemax="5" aria-valuenow="2.5">
</fancy-slider>

用户不依赖颜色就能理解所有内容吗?

不应将颜色用作传递信息的唯一方式,例如指示状态、提示用户回答或直观呈现数据。例如,如果您有饼图,请为每个切片提供标签和值,以便视障用户即使看不到各切片的开始和结束位置,也能理解这些信息:

一个包含标签和值的饼图,以确保可访问性。
便于访问的饼图。(来自 W3C Web 无障碍计划。)

对比度足够高吗?

组件中显示的任何文本内容都应满足最低 WCAG AA 级对比度阈值。考虑提供一个满足较高 AAA 阈值的高对比度主题背景,并确保当用户需要自定义对比度或不同的颜色时,可以应用用户代理样式表。 在设计组件时,您可以参考此色彩对比度检查工具

移动或闪烁的内容是否可停止且安全?

用户应能够暂停、停止或隐藏会移动、滚动或闪烁超过 5 秒的内容。一般情况下,请避免闪烁内容。

如果某些内容必须闪烁,请确保它每秒闪烁三次。

无障碍工具和测试

目前有 100 多种工具可用于评估网站及其组件的可访问性。有些工具是自动化的,而有些工具则需要手动测试。

以下是几个建议供您参考:

  • Axe 可为您选择的框架或浏览器提供自动化的无障碍功能测试。Axe Puppeteer 可用于编写自动化无障碍功能测试。
  • Lighthouse 无障碍功能审核提供了实用的数据洞见,可帮助您发现常见的无障碍功能问题。无障碍功能得分是根据 Axe 用户影响评估得出的所有无障碍功能审核的加权平均值。如需了解如何使用持续集成监控无障碍功能,请参阅 Lighthouse CI

    Lighthouse 无障碍功能审核的屏幕截图。

  • Tenon.io 可用于测试常见的无障碍功能问题。Tenon 跨构建工具、浏览器(通过扩展程序)甚至文本编辑器提供强大的集成支持。

  • 有许多特定于库和框架的工具可用于突出显示组件的无障碍功能问题。例如,使用 eslint-plugin-jsx-a11y 突出显示编辑器中的 React 组件的无障碍功能问题。

    一个代码编辑器的屏幕截图,其中存在由 eslint-plugin-jsx-a11y 标记的无障碍功能问题。

    如果您使用 Angular,codelyzer 还会提供编辑器中的无障碍功能审核:

    一个代码编辑器的屏幕截图,其中包含 Codelyzer 标记的无障碍功能问题。

使用辅助技术

  • 您可以使用无障碍功能检查器 (Mac) 或 Windows Automation API 测试工具AccProbe (Windows) 检查辅助技术查看 Web 内容的方式。您还可以前往 about://accessibility,查看 Chrome 创建的完整无障碍功能树。
  • 若要在 Mac 上测试屏幕阅读器支持情况,最佳方法是使用 VoiceOver 实用程序。使用 ⌘F5 启用或停用无障碍功能,使用 Ctrl+Option ←→ 在页面中移动,使用 Ctrl+Shift+Option + ↑↓ 在无障碍功能树中上下移动。如需更详细的说明,请参阅 VoiceOver 命令的完整列表VoiceOver 网络命令列表
  • 在 Windows 上,NVDA 是一款免费的开源屏幕阅读器。不过,视力正常的用户需要很长的学习时间。

    ChromeLens 的屏幕截图。

  • ChromeOS 具有内置屏幕阅读器

在改进 Web 无障碍功能方面,我们还有很长的路要走。 根据网络年鉴

  • 每 5 个网站中有 4 个文字与背景融为一体,导致无法阅读。
  • 49.91% 的网页仍未能为某些图片提供 alt 属性。
  • 在使用按钮或链接的网页中,只有 24% 包含标签。
  • 只有 22.33% 的网页为其所有表单输入提供了标签。

我们可以采取大量措施来打造人人都更容易获得的体验。