0%

可访问性 ARIA 深入

ARIA 是什么?

ARIA(Accessible Rich Internet Applications)是一套 WAI 规范,用于增强动态 Web 内容的可访问性。通过为元素添加特定属性,可以让屏幕阅读器等辅助技术理解元素语义和交互状态。

本章将彻底探讨 ARIA 的关键角色、常用属性、陷阱以及测试方法,目标是帮助前端开发者构建真正无障碍的 Web 应用。

基本角色

ARIA 定义了多种角色(role),用于描述元素功能。例如:

  • button - 可点击的按钮
  • alert - 弹出提示
  • navigation - 导航区域
  • dialog - 模态对话框
  • listbox / option - 可选择列表

使用示例:

1
2
3
4
5
<div role="navigation">
<ul>
<li><a href="/home">首页</a></li>
</ul>
</div>

如果使用原生元素(如 <nav><button>)可优先使用,因为它们自带语义,ARIA 主要用于增强非语义元素或复杂控件。

属性详解

状态与属性

  • aria-label:为元素提供可见文本之外的标签。
  • aria-labelledby:通过引用其他元素的 ID 提供标签。
  • aria-hidden:隐藏元素,使其对辅助技术不可见。
  • aria-expanded:描述可展开区域的展开状态。
  • aria-controls:指定元素控制的区域。
  • aria-live:指示动态内容需主动通知用户(如 politeassertive)。

示例:

1
2
3
4
<button aria-expanded="false" aria-controls="menu">菜单</button>
<ul id="menu" hidden>
<li>选项1</li>
</ul>

当按钮点击时,脚本更新 aria-expanded 并切换 hidden

复杂控件

  • aria-role="tabpanel"aria-selected 用于选项卡界面。
  • aria-valuenowaria-valueminaria-valuemax 用于滑块、进度条。
  • aria-describedby 用于关联描述文本。

示例进度条:

1
<div role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="60"></div>

场景与实践

模态对话框

  1. role="dialog"role="alertdialog"
  2. 当对话框打开时,将焦点移入并锁定(focus trap)。
  3. 使用 aria-modal="true" 表明其模式性质。
  4. 对话框关闭后,恢复到触发元素的焦点。

导航菜单与可访问性

导航菜单需要键盘可操作:

  1. 使用 tabindex="0" 使元素可通过 Tab 键获取焦点。
  2. 监听键盘事件(Enter、Space、Arrow keys)。
  3. 根据键盘操作更新 ARIA 状态,如 aria-expanded

表单元素增强

为不显式标签的输入添加 aria-label,例如图标搜索框:

1
<input type="text" aria-label="搜索" />

测试与验证

  • 使用屏幕阅读器 (NVDA, VoiceOver) 手动测试。
  • 借助自动化工具,如 aXe、Google Lighthouse 提示。
  • Chrome DevTools 的 Accessibility 面板可查看树状结构及 ARIA 属性。

常见误区

  • 误将 ARIA 属性应用于本身已有语义的元素。

    例如在 <button> 上使用 role="button" 是冗余的,且可能引起冲突。

  • 使用 aria-hidden="true" 隐藏对话框但没有阻止焦点进入。
  • 忽略动态内容更新时的 aria-live 设置,导致屏幕阅读器用户无法获知信息变化。

进阶技巧

  • 组件库综合规范:在封装可复用组件时为其添加默认 ARIA 属性。
  • 键盘导航规范化:实现 roving tabindex 模式,维护可聚焦元素列表,以便在菜单中使用箭头键。
1
2
3
4
5
6
7
8
9
const items = menu.querySelectorAll('[role="menuitem"]');
let current = 0;

menu.addEventListener('keydown', e => {
if (e.key === 'ArrowDown') {
current = (current + 1) % items.length;
items[current].focus();
}
});
  • 可访问性日志:在开发阶段记录 ARIA 应用情况并定期审计,便于团队共同维护。

案例分析

我们以一个简单的自定义下拉组件为例:

1
2
3
4
5
6
7
8
9
<div class="dropdown">
<button aria-haspopup="true" aria-expanded="false" id="dropdownBtn">
选择
</button>
<ul role="menu" aria-labelledby="dropdownBtn" hidden>
<li role="menuitem">选项1</li>
<li role="menuitem">选项2</li>
</ul>
</div>

JavaScript 部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const btn = document.getElementById('dropdownBtn');
const menu = document.querySelector('[role="menu"]');

btn.addEventListener('click', () => {
const expanded = btn.getAttribute('aria-expanded') === 'true';
btn.setAttribute('aria-expanded', String(!expanded));
menu.hidden = expanded;
});

menu.addEventListener('keydown', e => {
if (e.key === 'Escape') {
btn.click();
btn.focus();
}
});

该组件通过 ARIA 明确传达状态,同时支持键盘操作。

学习资源

总结

ARIA 并不是万能的,它只是辅助语义的工具。正确使用 ARIA 属性能让 Web 内容更具包容性,而滥用则可能引发混乱。牢记:优先使用语义 HTML,只有在必要时才添加 ARIA。通过持续实践和测试,你可以构建出符合 WCAG 标准的高质量应用,帮助更多用户无障碍访问你的项目。