TT Lab
开始
学习 学习路径 课程

HTML — 一个标签顶一项功能

可访问性树是另一份文档

在 TT Lab 中继续学习

一句话总结

浏览器会从 DOM 中另外生成一棵可访问性树(accessibility tree)。屏幕阅读器读取的不是屏幕,而是这棵树,而 ARIA 只修改这棵树——不会改变任何行为。

为什么需要它

被指出要改进可访问性时,人们通常会加上 role 和 aria-*。然而,结果常常比原来更糟。一再出现的调查表明,大量使用 ARIA 的页面,错误率反而比不用 ARIA 的页面更高。

原因很简单。ARIA 是一种承诺,而不是实现。 加上 role="button",就是告诉辅助技术“这是一个按钮”,从那一刻起,让它真正像按钮一样工作的全部责任都落在开发者身上。如果只说不做,屏幕阅读器用户会被告知这是按钮,点击之后却什么也没有发生。这比什么都不说还糟。

工作原理

从 DOM 生成可访问性树时,每个元素都会确定四项内容。

项目 是什么 示例
role 这是什么 button · link · heading · list
name 它叫什么 “保存”
state 当前是什么状态 按下 · 展开 · 禁用
value 值是多少 滑块的 40

原生 HTML 元素天生就具备这四项。<button> 的 role 是 button,里面的文字就是 name,disabled 就是 state,而焦点以及 Enter 和 Space 的处理都已经内置在浏览器中。

<div role="button"> 只得到了其中一项 role。其余三项以及行为,全都必须自己实现。MDN 对可访问性树的说明 和 ARIA in HTML 整理了这种关系。

五条规则

WAI-ARIA 使用规则 可以概括为五句话。重要性依次递减。

  1. 如果有可用的 HTML 元素,就用它。 只有在没有对应元素时才用 ARIA
  2. 不要改变原生语义。 <h2 role="tab"> 会把该项从标题列表中删除
  3. 所有交互式 ARIA 组件都必须能用键盘操作
  4. 不要在可获得焦点的元素上使用 role="presentation" 或 aria-hidden="true"
  5. 所有交互式元素都必须有可访问名称

第二条规则造成的事故最为悄无声息。role 不是叠加,而是覆盖。用了 <ul role="presentation">,这个列表就不再是列表,屏幕阅读器也不会说“共五项”。为了在设计上去掉圆点(bullet)而加上它,结果把整个结构都抹掉了,这种事在实际中很常见。

状态很容易说谎

aria-expanded、aria-selected、aria-checked、aria-current 这类状态属性,必须手动更新。 让箭头图标旋转的 CSS 会自动更新,但这些属性不会。

于是经常出现这样的事故——面板已经展开了,aria-expanded 却仍然是 false。对用眼睛看的人来说是展开的界面,对屏幕阅读器用户来说却是关闭的界面。两者之中有一个在说谎,而说谎的一方永远是辅助技术这一边。

aria-controls、aria-labelledby、aria-describedby 通过 id 指向其他元素。如果这个 id 不存在,浏览器不会报错,而是会悄悄地忽略。 在移动组件或按条件渲染时,引用经常会断开,但界面上没有任何变化,所以没有人知道。

实时区域

搜索结果数量、保存完成的提示、错误消息。后来才出现的文字,光凭这一点是不会被读出来的。 因为屏幕阅读器正在读别的地方。

有一点需要注意。实时区域必须事先就存在于 DOM 中。 如果在整个创建新元素的同时加上 role="alert",往往不会被读出来。更稳妥的做法是先放一个空容器,再修改其中的文字。

在现场相遇的样子

有三种情况反复出现。

第一,图标按钮没有名称。 <button><svg/></button> 没有名称,只会读作“按钮”。只需一行 aria-label="닫기"(韩文,意为“关闭”)就能解决,却是最常被遗漏的。

第二,没有隐藏装饰性图标。 用文字画出的图标(★、▶)会被原样读出来,发出类似“黑星 收藏”的声音。加上 aria-hidden="true" 就安静了。

第三,设计系统滥用 role。 一旦写错的 role 进入组件,就会沿着组件扩散到整个网站。这不是逐个修改页面能防住的,必须从组件层面来把控。

要记住的只有一点。糟糕的 ARIA 还不如没有 ARIA。 在修改之前,首先要问的问题不是“该加哪个 role”,而是“能做这件事的 HTML 元素是不是已经有了”。

下一项测验要确认什么

会确认可访问性树里装了什么、role 覆盖了什么,以及状态属性和实时区域会以怎样的方式悄悄失效。