无障碍树简介
想象一下,您正在仅为屏幕阅读器用户构建用户界面。在这里,您根本不需要创建任何视觉 UI,只需提供足够的信息供屏幕阅读器使用即可。
您将创建的是一种描述页面结构的 API,类似于 DOM API,但您可以减少信息和节点,因为很多信息仅对视觉呈现有用。它可能看起来像这样。

这基本上是浏览器实际呈现给屏幕阅读器的内容。浏览器获取 DOM 树并将其修改为对辅助技术有用的形式。我们将这个修改后的树称为无障碍树。
您可以将无障碍树可视化为有点像 90 年代的旧网页:一些图像、许多链接,可能还有一个字段和一个按钮。

像这样在页面上向下视觉扫描会给您带来类似于屏幕阅读器用户获得的体验。界面就在那里,但它简单而直接,很像无障碍树界面。
无障碍树是大多数辅助技术与之交互的对象。流程大致如下。
- 应用程序(浏览器或其他应用)通过 API 向辅助技术公开其 UI 的语义版本。
- 辅助技术可以使用它通过 API 读取的信息,为用户创建备用用户界面呈现。例如,屏幕阅读器创建一个用户可以听到应用语音表示的界面。
- 辅助技术还可以允许用户以不同的方式与应用交互。例如,大多数屏幕阅读器都提供钩子,允许用户轻松模拟鼠标点击或手指轻击。
- 辅助技术通过无障碍 API 将用户意图(例如“点击”)中继回应用。然后,应用有责任在原始 UI 的上下文中适当地解释该操作。
对于 web 浏览器,每个方向都有一个额外的步骤,因为浏览器实际上是在其中运行的 web 应用的平台。因此,浏览器需要将 web 应用转换为无障碍树,并且必须确保根据来自辅助技术的用户操作在 JavaScript 中触发适当的事件。
但这都是浏览器的责任。我们作为 web 开发人员的工作只是意识到正在发生的事情,并开发利用此过程的 web 页面,为我们的用户创建无障碍体验。
我们通过确保正确表达页面的语义来实现这一点:确保页面中的重要元素具有正确的无障碍角色、状态和属性,并确保我们指定无障碍名称和描述。然后,浏览器可以让辅助技术访问该信息以创建自定义体验。
原生 HTML 中的语义
浏览器可以将 DOM 树转换为无障碍树,因为很多 DOM 都具有隐式语义含义。也就是说,DOM 使用浏览器可识别并在各种平台上可预测地工作的原生 HTML 元素。因此,链接或按钮等原生 HTML 元素的无障碍功能是自动处理的。我们可以通过编写表达页面元素语义的 HTML 来利用这种内置的无障碍功能。
但是,有时我们使用的元素看起来像原生元素,但实际上不是。例如,这个“按钮”根本不是按钮。
它可以用 HTML 以多种方式构建;下面显示了一种方式。
<div class="button-ish">Give me tacos</div>
当我们不使用实际的 button 元素时,屏幕阅读器无法知道它已落在什么位置。此外,我们还必须额外添加 tabindex 才能使其对仅使用键盘的用户可用,因为按照现在的编码方式,它只能用鼠标使用。
我们可以通过使用常规的 button
元素而不是 div
轻松解决此问题。使用原生元素还具有为我们处理键盘交互的优势。请记住,您不必因为使用原生元素而失去时尚的视觉效果;您可以对原生元素进行样式设置,使其看起来像您想要的样子,并且仍然保留隐式语义和行为。
前面我们提到,屏幕阅读器会宣布元素的角色、名称、状态和值。通过使用正确的语义元素,角色、状态和值都已涵盖,但我们还必须确保元素的名称可被发现。
广义上讲,名称有两种类型
- 可见标签,所有用户都使用它们将含义与元素关联,以及
- 文本替代方案,仅在不需要视觉标签时使用。
对于文本级元素,我们不需要做任何事情,因为根据定义,它将具有一些文本内容。但是,对于输入或控件元素以及图像等视觉内容,我们需要确保指定名称。事实上,为任何非文本内容提供文本替代方案是 WebAIM 清单上的第一项。
一种方法是遵循他们的建议,“表单输入具有关联的文本标签。” 有两种方法可以将标签与表单元素(例如复选框)关联。这两种方法都会使标签文本也成为复选框的点击目标,这对鼠标或触摸屏用户也很有帮助。要将标签与元素关联,请执行以下操作之一
- 将 input 元素放在 label 元素内
<label> <input type="checkbox">Receive promotional offers? </label>
或
- 使用 label 的
for
属性并引用元素的id
<input id="promo" type="checkbox">
<label for="promo">Receive promotional offers?</label>
当复选框已正确标记时,屏幕阅读器可以报告该元素具有复选框的角色,处于选中状态,并且名为“接收促销优惠?”。
