无障碍树简介
假设您要仅面向屏幕阅读器用户构建界面。在这里,您根本不需要创建任何视觉界面,而只需提供足够的信息供屏幕阅读器使用。
您要创建的是一种描述页面结构的 API,与 DOM API 类似,但您可以减少信息和节点数量,因为其中很多信息只对视觉呈现有用。代码可能如下所示:
![屏幕阅读器 DOM API 模型](https://web.developers.google.cn/static/articles/the-accessibility-tree/image/screen-reader-dom-api-moc-86f15b848dd25.jpg?authuser=8&hl=hu)
这基本上就是浏览器实际呈现给屏幕阅读器的内容。浏览器获取 DOM 树并将其修改为有助于辅助技术的形式。我们将这个经过修改的树称为无障碍树。
您可以将无障碍功能树想象成有点像 20 世纪 90 年代的旧网页:几张图片、许多链接,或许是一个字段和一个按钮。
![20 世纪 90 年代风格的网页](https://web.developers.google.cn/static/articles/the-accessibility-tree/image/a-1990s-style-web-page-71a74592e602e.png?authuser=8&hl=hu)
目视向下浏览此类页面所得到的体验与屏幕阅读器用户获得的体验类似。这里有这个接口,但它简单而直接,就像无障碍树接口一样。
无障碍功能树是大多数辅助技术与之交互的对象。具体流程如下所示。
- 应用(浏览器或其他应用)通过 API 向辅助技术公开其界面的语义版本。
- 辅助技术可能会使用通过 API 读取的信息来为用户创建替代的界面呈现方式。例如,屏幕阅读器可以创建一个能让用户听到应用语音表示的界面。
- 辅助技术还可以允许用户以不同的方式与应用互动。例如,大多数屏幕阅读器都提供钩子,以便用户轻松模拟鼠标点击或手指点按。
- 辅助技术通过无障碍功能 API 将用户意图(例如“点击”)传回应用。然后,应用就负责在原始界面的上下文中正确解读操作。
对于网络浏览器,在每个方向上都要多执行一个步骤,因为浏览器实际上是一个供其内部运行的 Web 应用的平台。因此,浏览器需要将 Web 应用转换为无障碍树,并且必须确保在 JavaScript 中根据来自辅助技术的用户操作触发适当的事件。
但这全都是浏览器的责任。作为 Web 开发者,我们的任务只是要注意这一过程,并开发网页能够利用此过程为用户打造无障碍体验。
为此,我们需要确保正确表达页面的语义:确保页面中的重要元素具有正确的无障碍角色、状态和属性,以及我们指定无障碍名称和说明。然后,浏览器可以让辅助技术访问该信息以打造自定义体验。
原生 HTML 中的语义
浏览器可以将 DOM 树转换为无障碍树,因为 DOM 的大部分内容具有隐式语义含义。也就是说,DOM 采用的原生 HTML 元素能被浏览器识别,并能以可预测的方式在各种平台上运行。因此,链接或按钮等原生 HTML 元素的无障碍功能是自动处理的。我们可以通过编写表达页面元素语义的 HTML 来充分利用这一内置无障碍功能。
不过,有时我们使用的元素虽然看起来像原生元素,但实际却并非如此。例如,此“按钮”就根本不是按钮。
它可以在 HTML 中通过任意多种方式构建;下面显示了其中一种方式。
<div class="button-ish">Give me tacos</div>
当我们不使用实际的按钮元素时,屏幕阅读器无法知道它已经加载了什么内容。此外,我们还必须执行额外的添加 tabindex 的工作,以便仅使用键盘的用户也能使用它,因为按照现在的编码,它只能通过鼠标使用。
我们可以使用常规 button
元素而不是 div
来轻松解决此问题。使用原生元素还有一项好处,就是为我们处理键盘交互。此外,请注意,您不必只因使用原生元素而失去出色的视觉效果;您可以为原生元素设置样式,使其看起来符合您想要的外观,同时仍然保留隐式语义和行为。
我们之前提到过,屏幕阅读器会读出元素的角色、名称、状态和值。通过使用正确的语义元素,可以涵盖角色、状态和值,但我们还必须确保使元素的名称可被检测到。
一般来说,名称分为两种类型:
- 可见标签:所有用户都使用它们将含义与元素相关联;
- 文本替代项:仅在不需要视觉标签时使用。
对于文本级元素,我们无需执行任何操作,因为按照定义,它将包含一些文本内容。不过,对于输入或控件元素以及图片等视觉内容,我们需要确保指定名称。事实上,为任何非文本内容提供文本替代项是 WebAIM 核对清单上的第一项。
一种方法是遵循他们的建议,即“表单输入具有关联的文本标签”。您可以通过两种方式将标签与表单元素(如复选框)相关联。这两种方法都会导致标签文本也成为复选框的点击目标,这对鼠标或触摸屏用户也很有用。要将标签与元素相关联,请执行以下任一操作:
- 将输入元素放在标签元素内
<label> <input type="checkbox">Receive promotional offers? </label>
或
- 使用标签的
for
属性并引用元素的id
<input id="promo" type="checkbox">
<label for="promo">Receive promotional offers?</label>
正确标记复选框后,屏幕阅读器可以报告该元素的角色为复选框,处于选中状态,并且名为“接收促销优惠?”。
![VoiceOver 的屏幕文字输出,显示了复选框的语音标签](https://web.developers.google.cn/static/articles/the-accessibility-tree/image/on-screen-text-output-vo-2bf0c33d65f23.png?authuser=8&hl=hu)