ARIA入门指南:从概念到实战的完整解析

本文深入探讨ARIA(无障碍富互联网应用)的核心概念、使用规则和常见误区,涵盖角色声明、状态管理、浏览器支持等关键技术细节,帮助开发者构建更易访问的Web体验。

当我开始学习ARIA时,希望有人告诉我的事

无障碍富互联网应用(ARIA)是处理Web无障碍性时不可避免的技术。也就是说,每个人在某个时间点都是第一次学习ARIA。

如果你以前没有遇到过ARIA,太好了!这是一个学习新东西的机会。如果你以前听说过ARIA,这篇文章可能会帮助你更好地理解它,甚至可能教你一些新东西!

这些都是我希望在我开始Web无障碍之旅时有人告诉我的事情。本文将:

  • 提供如何将ARIA作为一个概念来处理的心态,
  • 揭穿一些常见的误解,以及
  • 提供一些指导性思考,帮助你更好地理解和使用它。

我希望通过这样做,这篇文章能够帮助使Web设计和开发中一个经常被忽视但至关重要的角落更容易接近。

这篇文章不是什么

这不是一本关于如何使用ARIA构建无障碍网站和Web应用的食谱书。它也不是关于如何修复无障碍体验的指南。很多无障碍工作都是高度情境化的。我不知道你的项目或组织的具体需求,所以在这里尝试给出建议可能弊大于利。

相反,把这篇文章看作是一个“出发前须知”指南。我希望给你一个良好的心态来接近ARIA,并强调在你开始旅程时需要注意的事项。那么,让我们开始吧!

那么,什么是ARIA?

ARIA是你在没有更好的本地HTML元素或属性来传达交互性、目的和状态时所求助的东西。

把它想象成你撒入标记中以增强事物的香料。

将ARIA添加到你的HTML标记中是一种向网站或Web应用提供额外信息的方式,供屏幕阅读器和语音控制软件使用。

  • 交互性意味着内容可以被激活或操作。一个例子是导航到链接的目的地。
  • 目的意味着某物的用途。一个例子是用于收集某人姓名的文本输入。
  • 状态意味着内容当前所处的状态,由状态、属性和值控制和放置。一个例子是可以展开或折叠的手风琴面板。

以下是一个说明,帮助传达我的意思:

(大型预览)

HTML按钮元素的存在将指示辅助技术将其报告为按钮,让某人知道它可以被激活以执行预定义的操作。

文本字符串“Mute”的存在将被辅助技术报告,以提示某人按钮的用途。

aria-pressed="true"的存在意味着某人或某物之前已经激活了按钮,并且它现在处于一个“按下”状态,维持其动作。

这种整体模式将让使用辅助技术的人知道:

  • 某物是否具有交互性,
  • 它执行哪种交互行为,以及
  • 它的当前状态。

ARIA的历史

ARIA已经存在很长时间了,第一个版本于2006年9月26日发布。

(大型预览)

ARIA的创建是为了在HTML的局限性和使交互体验可被辅助技术理解的需求之间提供一座桥梁。

“ARIA的最新版本是1.2版,于2023年6月6日发布。1.3版预计很快发布,你可以在Craig Abbott的这篇优秀文章中阅读更多关于它的信息。

你可能也会看到它被称为WAI-ARIA,其中WAI代表“Web无障碍倡议”。WAI是W3C的一部分,该组织为Web制定标准。也就是说,我认识的大多数无障碍从业者在书面和口头交流中称其为“ARIA”,并省略“WAI-”部分。

ARIA的精神反映了它创建的时代

原因很简单:过去的Web比现在不成熟得多。2006年最流行的操作系统是Windows XP。iPhone还不存在;它是在一年后发布的。

从非常高的层面来看,ARIA是这个时间段操作系统交互范式的快照。这是因为ARIA重新创建了它们。

图片来源:Microsoft Windows XP Wiki。(大型预览)

心态

具有可点击、可滑动和可拖动表面等功能的智能手机远不那么常见。单页应用“Web应用”体验也很罕见,基于Ajax的方法最流行。这意味着我们必须使用2006年的技术来构建今天的体验。在某种程度上,这是一件好事。它迫使我们接受新颖的体验并审视它们。

无法分解成更小、更集中的部分并映射到ARIA模式的交互很可能无法访问。这是因为它们将无法由辅助技术操作或在较旧或较不流行的设备上运行。

我可能有偏见,但我认为这些无法转换的新颖交互也作为一个警告,表明普通观众会发现它们令人困惑,因此无法使用。考虑到互联网服务于:

  • 未知数量的人,
  • 使用未知数量的设备,
  • 每个设备都有未知数量的个人定制,
  • 他们有自己的独特需求和情况,并且
  • 有未知的动机因素。

交互期望

当代对基于键盘的Web内容交互的期望——复选框、单选按钮、模态框、手风琴等——源自Windows XP及其前身操作系统。这些交互模型作为使用辅助技术的老年人的肌肉记忆被延续下来。依赖辅助技术的年轻人也学习这些事实上的标准,从而继续这个循环。

这对你意味着什么?使用键盘与你的网站或Web应用交互的人很可能会首先尝试这些基于Windows操作系统的键盘快捷键。这意味着诸如按下:

  • Enter键导航到链接的目的地,
  • 空格键激活按钮,
  • Home和End键跳转到项目列表的开头或结尾,等等。

它也是一份活文档

这并不是说ARIA已经停滞不前。它不断被修改,有新的添加、删除和澄清。记住,它现在处于1.2版,1.3版即将到来。

与此同时,HTML作为一种语言也反映了这种演变。元素最初是为了支持面向文档的Web而创建的,并逐渐演变为支持更动态、类似应用的体验。这里的好处是,这一切都是公开进行的,如果你有动力,你可以贡献其中。

ARIA有使用规则

ARIA的文档中包含五条规则,以帮助指导你如何接近它:

  1. 尽可能使用本地元素。 一个例子是使用锚元素(<a>)作为链接,而不是带有点击处理程序和链接角色的div。
  2. 如果可能,不要调整本地元素的语义。 一个例子是尝试使用标题元素作为选项卡,而不是将标题包装在语义中性的div中。
  3. 任何交互式的东西都必须可以通过键盘操作。 如果你不能用键盘使用它,它就不可访问。句号。
  4. 不要在可聚焦元素上使用role="presentation"aria-hidden="true"。 这会使意图交互的东西无法被辅助技术使用。
  5. 交互式元素必须被命名。 一个例子是使用文本字符串“Print”作为按钮元素。

遵守这五条规则将对你大有帮助。以下是更多上下文,以提供更多支持。

ARIA有一个分类法

ARIA有一个结构化的语法,它以角色以及状态和属性为中心。

角色

角色是辅助技术读取然后宣布的内容。很多人用语义来简称。HTML元素有隐含的角色,这就是为什么锚元素会被屏幕阅读器宣布为链接,无需额外工作。

(大型预览)

如果用例需要,隐含角色几乎总是更好使用。回想一下这里的第一条ARIA规则。这通常是数字无障碍从业者在说“只需使用语义HTML”时所指的。

偏爱隐含角色有很多原因。主要考虑的是更好地保证支持跨未知数量的操作系统、浏览器和辅助技术组合。

角色有类别,每个类别都有自己的目的。抽象角色类别值得注意,因为它是一个组织超级类别,不打算由作者使用:

抽象角色用于本体论。作者不得在内容中使用抽象角色。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!-- 这不会工作,不要这样做 -->
<h2 role="sectionhead">
  Anatomy and physiology
</h2>

<!-- 改为这样做 -->
<section aria-labeledby="anatomy-and-physiology">
  <h2 id="anatomy-and-physiology">
    Anatomy and physiology
  </h2>
</section>

此外,同样地,你只能在某些东西上声明ARIA,你只能将一些ARIA声明为其他ARIA声明的子级。一个例子是listitem角色,它要求其父元素存在list角色。

那么,确定角色是否需要父声明的最佳方法是什么?答案是查看官方定义。

状态和属性

状态和属性是ARIA整体分类法的另外两个主要部分。

隐含角色由语义HTML提供,显式角色由ARIA提供。两者都描述了元素是什么。状态以辅助技术可以理解的方式描述该元素的特征。这是通过属性声明及其伴随值完成的。

(大型预览)

ARIA状态可以快速或缓慢地改变,无论是由于人类交互还是应用状态。当状态由于人类交互而改变时,它被认为是“非托管状态”。在这里,开发人员必须提供底层JavaScript逻辑来控制交互。

当状态由于应用(例如,操作系统、Web浏览器等)而改变时,这被认为是“托管状态”。在这里,应用自动提供底层逻辑。

如何声明ARIA

将ARIA视为HTML属性的扩展,一套名称/值对。有些值是预定义的,而其他值是作者提供的:

(大型预览)

对于前面图形中的示例,aria-live的polite值是三个预定义值(off、polite和assertive)之一。对于aria-label,“Save”是作者手动提供的文本字符串。

你在HTML元素上声明ARIA的方式与声明其他属性的方式相同:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 
  将id值“carrot”应用于div
-->
<div id="carrot"></div>

<!-- 
  从辅助技术隐藏此段落元素的内容
-->
<p aria-hidden="true">
  Assistive technology can't read this
</p>

<!-- 
  提供“Stop”的可访问名称,
  并传达按钮当前被按下。
  类型属性值为“button”防止浏览器表单提交。
-->
<button 
  aria-label="Stop"
  aria-pressed="true"
  type="button">
  <!-- SVG图标 -->
</button>

其他使用说明:

  • 你可以在一个HTML元素上放置多个ARIA声明。
  • 在HTML元素上声明ARIA时的顺序无关紧要。
  • 可以在元素上放置的ARIA声明数量没有限制。注意,你添加的越多,你引入的复杂性就越大,而更多的复杂性意味着事情可能破坏或无法按预期运行的机会更大。
  • 你可以在HTML元素上声明ARIA,也可以有其他非ARIA声明,例如class或id。这里的声明顺序也无关紧要。

可能也有帮助的是,知道布尔属性在ARIA中与HTML中的处理方式有些不同。Hidde de Vries在他的文章“HTML和ARIA中的布尔属性:有什么区别?”中写了关于这个的内容。

没有很多ARIA是“硬编码”的

在这种上下文中,“硬编码”意味着直接将静态属性或值声明写入你的组件、视图或页面。

很多ARIA被设计为基于应用状态或作为某人操作的响应动态应用或条件修改。一个例子是显示和隐藏的披露模式:

  • ARIA的aria-expanded属性在false和true之间切换,以传达披露是处于展开还是折叠状态。
  • HTML的hidden属性被条件性地移除或添加,以显示或隐藏披露的完整内容区域。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="disclosure-container">
  <button 
    aria-expanded="false"
    class="disclosure-toggle"
    type="button">
    How we protect your personal information
  </button>
  <div 
    hidden
    class="disclosure-content">
    <ul>
      <li>Fast, accurate, thorough and non-stop protection from cyber attacks</li>
      <li>Patching practices that address vulnerabilities that attackers try to exploit</li>
      <li>Data loss prevention practices help to ensure data doesn't fall into the wrong hands</li>
      <li>Supply risk management practices help ensure our suppliers adhere to our expectations</li>
    </ul>
    <p>
      <a href="/security/">Learn more about our security best practices</a>.
    </p>
  </div>
</div>

你在网络上会遇到的一个常见硬编码ARIA声明是使按钮内的SVG图标具有装饰性:

1
2
3
4
5
6
<button type="button>
  <svg aria-hidden="true">
    <!-- SVG代码 -->
  </svg>
  Save
</button>

在这里,字符串“Save”是某人理解按钮在激活时会做什么所必需的。伴随的图标在视觉上帮助这种理解,但被认为是冗余的,因此具有装饰性。

在已经隐含使用该角色的东西上声明ARIA角色不会使其“额外”可访问

如果你使用语义HTML,隐含角色就是你所需要的。通过ARIA显式声明其角色不会带来任何额外优势。

1
2
3
4
5
6
7
8
<!-- 
  你不需要在这里声明role="button"。
  使用<button>元素将使辅助技术将其宣布为按钮。
  role="button"声明是冗余的。
 -->
<button role="button">
  Save
</button>

你可能偶尔会在HTML分区元素上遇到这些冗余声明,例如<main role="main"><footer role="contentinfo">。这不再需要,你可以只使用<main><footer>元素。

原因是历史性的。这些声明是为了支持原因而完成的,因为这是一种权宜之计技术,用于需要更新以支持这些当时新的HTML元素的辅助技术。

当代辅助技术不需要这些冗余声明。以我们不再需要为CSS border-radius属性使用供应商前缀的方式思考。

注意:此指导有一个例外。在某些情况下,某些复杂和复杂的标记模式无法按预期用于辅助技术。在这些情况下,我们希望将隐式角色硬编码为显式ARIA以确保其工作。此辅助技术支持问题将在本文后面更详细地介绍。

你不需要说控件是什么;那是角色的用途

屏幕阅读器会宣布隐式和显式角色。你不需要为交互元素的文本字符串或aria-label等内容包含该部分。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<!-- 不要这样做 -->
<button 
  aria-label="Save button"
  type="button">
  <!-- 图标SVG -->
</button>

<!-- 改为这样做 -->
<button 
  aria-label="Save"
  type="button">
  <!-- 图标SVG -->
</button>

如果我们为我们的保存按钮使用字符串值“Save button”,屏幕阅读器会宣布类似“Save button, button”的内容。那是冗余和令人困惑的。

ARIA角色有非常具体的含义

我们有时 colloquially 将网站和Web应用导航称为菜单,尤其是如果它是电子商务风格的巨型菜单。

在ARIA中,菜单意味着非常具体的东西。不要想到全局或页面内导航之类的。在这种上下文中,将菜单视为当你单击应用程序菜单栏上的编辑菜单按钮时出现的内容。

Notepad,Windows 11。(大型预览)

因为其名称乍一看似乎合适而错误地使用角色,会对没有视觉UI上下文的人造成混淆。他们的期望将随着角色的宣布而设定,然后当它不按预期方式行动时被颠覆。

想象一下,如果你单击一个链接,它不是带你到另一个网页,而是向你的打印机发送完全不相关的东西。有点像那样。

声明role="menu"是一个常见错误应用角色的例子,但还有其他。知道角色用途的最佳方法?直接查看来源并阅读。

某些角色被禁止具有可访问名称

这些角色是caption、code、deletion、emphasis、generic、insertion、paragraph、presentation、strong、subscript和superscript。

这意味着你可以尝试为这些元素之一提供可访问名称——比如通过aria-label——但它不会工作,因为它被ARIA语法规则禁止。

1
2
3
4
5
6
7
8
9
<!-- 这不会工作-->
<strong aria-label="A 35% discount!">
  $39.95
</strong>

<!-- 这也不会 -->
<code title="let JavaScript example">
  let submitButton = document.querySelector('button[type="submit"]');
</code>

对于这些示例,回想角色是隐含的,源自声明的HTML元素。

注意,有时浏览器会无论如何尝试并覆盖作者指定的字符串值。这种覆盖对所有相关方来说都是一个令人困惑的行为,这导致了规则的首先建立。

你不能编造ARIA并期望它工作

我目睹过一些开发人员猜测添加CSS类,例如.background-red.text-white,到他们的标记中,并在设计视觉更新正确时得到奖励。

这工作的原因是有人之前将这些类添加到项目中。对于ARIA,添加我们可以使用的内容的人是无障碍富互联网应用工作组。这意味着每个新版本的ARIA都有一组预定义的属性和值。然后辅助技术被更新以解析这些属性和值,尽管这并不总是保证。

声明不属于该预定义集的ARIA意味着辅助技术将不知道它是什么,因此不会宣布它。

1
2
3
4
5
6
7
8
9
<!-- 
  ARIA中没有“selectpanel”角色。
  因此,此代码将被宣布为按钮而不是选择面板。
-->
<button 
  role="selectpanel"
  type="button">
  Choose resources
</button>

ARIA静默失败

这涉及到前一部分,其中ARIA不会理解在其有限词汇表之外所说的单词。

对于格式错误的ARIA,没有控制台错误。也没有警报对话框、哔哔声或闪烁灯用于你的操作系统、浏览器或辅助技术。这个事实是为什么用实际辅助技术测试如此重要的另一个原因。

你也不必成为专家。如果你将某些东西设置为宣布为特定状态,而辅助技术在其默认配置中不宣布该状态,那么你的代码很可能需要更新。

ARIA只向辅助技术暴露某物的存在

将ARIA应用于某物不会自动“解锁”功能。它只向辅助技术发送关于交互内容应如何行为的提示。

对于像屏幕阅读器这样的辅助技术,该提示可能是如何宣布某物。对于像可刷新盲文显示器这样的辅助技术,它可能是如何升高和降低其引脚。例如,在div元素上声明role="button"不会自动使其可点击。你仍然需要:

  • 在JavaScript中定位div元素,
  • 将其绑定到点击事件,
  • 编写点击时执行的交互逻辑,然后
  • 容纳所有其他预期行为。

这一切让我想知道为什么你不能节省一些工作并首先使用按钮元素,但那是另一天的另一个故事。

此外,通过ARIA调整元素的角色不会修改元素的本地功能。例如,你可以在div元素上声明role="image"。但是,尝试在div上声明alt或src属性将不起作用。这是因为alt和src不是div支持的属性。

(大型预览)

在某物上声明ARIA角色将覆盖其语义,但不覆盖其行为

这涉及到前一部分关于ARIA只暴露某物的存在。不要忘记某些HTML元素具有内置的主要和次要交互功能。

例如,锚元素的主要功能是导航到为其href属性提供的任何URL值。锚元素的次要功能包括复制URL值、在新选项卡或隐身窗口中打开它等等。

Chrome on macOS。注意对用户安装的浏览器扩展的支持。(大型预览)

这些次要功能仍然保留。然而,可能不明显的是某人可以使用它们——或以他们期望的方式使用它们——取决于宣布的内容。

相反的情况也是真的。当元素没有功能时,调整其角色不会授予它任何新能力。记住,ARIA只宣布。这就是为什么那个分配了按钮角色的div在点击时如果不存在伴随的JavaScript逻辑也不会做任何事情。

(大型预览)

你将需要声明ARIA以使某些交互可访问

之前的很多内容可能使ARIA

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计