在构建现代 Web 应用时,HTML 的语义化不仅降低了开发成本,更是实现无障碍访问的基石。无障碍设计涵盖色彩对比、控件尺寸、辅助设备兼容等多个维度,而其中与 HTML 强相关的部分,主要包括对物理键盘、屏幕阅读器及移动端虚拟键盘的良好支持。
键盘的无障碍访问
键盘无障碍访问是 Web 可访问性的基础,不仅对视障人群必不可少,正常用户同样依赖它(如回车提交表单、方向键操作下拉列表)。随着智能电视普及,遥控器作为键盘的替代,进一步放大了键盘可访问性的必要性。实现这一点并不复杂:所有可点击控件应优先使用 <a> 或 <button> 元素,它们天然支持 Tab 键索引和回车触发。若不得已使用 <div> 或 <span> 模拟按钮,则必须设置 tabindex="0"。
tabindex 属性
描述
tabindex 全局属性允许开发者控制 HTML 元素的可聚焦性,决定元素是否参与顺序焦点导航,并设定其在顺序焦点导航中的相对顺序。
取值
tabindex="-1":可以通过鼠标点击或 JavaScript 的focus()方法获得焦点,但它不会参与顺序键盘导航,不能通过 Tab 键聚焦。tabindex="0":元素应参与顺序键盘导航,其导航顺序位于所有正tabindex值之后。这些元素的焦点导航顺序由它们在文档源代码中的出现顺序决定。tabindex="正整数值":不推荐使用,元素应参与顺序键盘导航,其导航顺序由该数值决定。数值越小,优先级越高。tabindex="4"的元素在tabindex="5"和tabindex="0"之前获得焦点,但在tabindex="3"之后。- 如果多个元素具有相同的正
tabindex值,它们之间的相对顺序遵循文档源代码中的位置。 tabindex的最大值为32767。
Web 开发者应避免使用正数值,推荐使用
0或-1,以确保顺序和可访问性的清晰。
默认可聚焦元素
某些 HTML 元素默认具有可聚焦性,用户代理会为其隐式设置 tabindex="0"。这些元素包括:
- 带有
href属性的<a>或<area>元素 <button>元素<iframe>元素<input>元素<object>元素<select>元素<textarea>元素- SVG 的
<a>元素 - 为
<details>元素提供摘要的<summary>元素
开发者不应为上述元素添加 tabindex 属性,除非需要改变其默认行为(例如,使用负值将其从焦点导航顺序中移除)。
注意事项
tabindex属性不得用于<dialog>元素。
accesskey 属性
描述
accesskey 全局属性用于为当前元素提供生成键盘快捷键的提示。
浏览器与平台的激活方式
激活 accesskey 的方式取决于浏览器及其运行平台:
| 浏览器 | Windows | Linux | Mac |
|---|---|---|---|
| Firefox | Alt + Shift + key |
Alt + Shift + key |
Control + Option + key 或 Control + Alt + key |
| MS Edge | Alt + key |
Control + Option + key或 Control + Option + Shift + key |
Control + Option + key |
| Google Chrome | Alt + key |
Control + Option + key或 Control + Option + Shift + key |
Control + Option + key |
| Safari | 不适用 | 不适用 | Control + Option + key |
| Opera | Alt + key |
Alt + Shift + key |
Control + Alt + key |
使用示例
示例1:搜索功能
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Accesskey 示例</title>
<style>
body {
max-width: 1000px;
margin: 0 auto;
padding: 40px;
font-family: system-ui, sans-serif;
}
input {
width: 100%;
padding: 12px 16px;
border: 1px solid #ccc;
font-size: 16px;
border-radius: 8px;
outline: none;
}
input:focus {
border-color: #4a90e2;
box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.2);
}
kbd {
padding: 2px 8px;
background: #f0f0f0;
font-family: monospace;
font-size: 14px;
border-radius: 4px;
}
</style>
</head>
<body>
<h1>欢迎来到我们的网页</h1>
<p>按下 <kbd>Alt</kbd> + <kbd>/</kbd> 将聚焦到搜索框。</p>
<input type="text" id="search" placeholder="请输入搜索内容" accesskey="/" />
</body>
</html>

屏幕阅读无障碍访问
在美国,如果网页无法让残疾人正常访问,企业可能会被要求重新设计网站,不仅涉及金钱损失,还要支付律师费。国内前几年也出台了老龄化适配政策,随后也出现了专门支持无障碍访问的公司。可见,对无障碍访问的学习还是很有必要的,不求精通,但至少要掌握一些基础知识。
尽可能使用原生元素和属性
目前,国内 Web 产品对无障碍访问的支持比较糟糕。实际上,只要你能够在网页开发时尽可能使用语义精准的 HTML 元素,所实现产品的无障碍访问能力已经超过绝大多数公司的产品。
介绍一些关于 Web 无障碍访问的常识性知识,这些是很多人容易犯错的地方:
1. 图标按钮的处理
有些按钮没有文字,仅有一个小图标。很多人图省事使用 <span> 元素,这是糟糕的做法。外面一定要嵌套 <button> 按钮;如果是链接,则可以使用 <a> 元素。
html
<span class="icon-btn"></span>
<button><span class="icon-btn"></span></button>
<a href=""><span class="icon-btn"></span></a>
2. 悬停效果需配合点击切换
桌面端网页有很多鼠标悬停显示下拉列表的效果,这些效果一定要同时设置点击切换显隐,否则触摸屏、屏幕阅读器或键盘访问就会有障碍。
html
<!-- 错误:仅悬停触发 -->
<div class="dropdown" onmouseenter="showMenu()">
<span>菜单</span>
<div class="menu">...</div>
</div>
<!-- 正确:同时支持点击和悬停 -->
<div class="dropdown"
onmouseenter="showMenu()"
onclick="toggleMenu()">
<button>菜单</button>
<div class="menu">...</div>
</div>
3. 弹窗必须有明确的关闭按钮
弹出层或弹出框一定要有关闭按钮,按钮最好位于右上角。如果这与视觉设计稿不符,可以设置透明度为 0,这对视力有障碍的用户会非常友好。
html
<!-- 错误:没有关闭按钮 -->
<div class="modal">
<p>操作成功</p>
</div>
<!-- 正确:包含关闭按钮 -->
<div class="modal">
<button class="close-btn" onclick="closeModal()">✕</button>
<p>操作成功</p>
</div>
<!-- 正确:视觉透明但可聚焦 -->
<div class="modal">
<button class="close-btn visually-hidden" onclick="closeModal()">关闭</button>
<p>操作成功</p>
</div>
4. 聚焦状态必须有样式变化
所有控件元素在聚焦时一定要有样式变化,建议使用 outline 添加轮廓。
css
/* 错误:移除 outline 且无替代方案 */
a, button {
outline: none;
}
/* 正确:保留 outline 或自定义聚焦样式 */
a:focus, button:focus {
outline: 2px solid #4a90e2;
outline-offset: 2px;
}
/* 正确:自定义聚焦样式 */
input:focus {
border-color: #4a90e2;
box-shadow: 0 0 0 2px rgba(74,144,226,0.2);
}
5. 图形化内容必须提供文字
html
<!-- 错误:仅图标,无文字 -->
<i class="icon-free" title="图标"></i>
<!-- 正确:包含可识别文字 -->
<i class="icon-free" title="免费">免费</i>
6. 图片必须使用 并设置 alt
只要不是无关紧要的装饰性图片,一定要使用 <img> 元素,且必须设置 alt 描述值。如果图片带有角标等信息,可以一并写在 alt 属性中。
html
<!-- 错误:无 alt 属性 -->
<img src="cover.jpg">
<!-- 正确:设置 alt 描述 -->
<img src="cover.jpg" alt="书籍封面:Web开发权威指南">
<!-- 正确:角标信息也写入 alt -->
<img src="cover.jpg" alt="青城道长限时免费">
7. 不要单独使用 SVG 图像
哪怕设置了 <title> 元素,SVG 内的文字也不会被读取。例如:
html
<!-- 错误:title 不会被朗读 -->
<svg class="icon-arrow">
<title>返回</title>
<use xlink:href="#icon-arrow"></use>
</svg>
其中的"返回"二字并不会被读取,而是会朗读宽泛的"图像"。不过,如果外面有链接元素,则在 VoiceOver 下就会朗读"返回,链接",因为此时 SVG 从图像性质变成了链接内容:
html
<!-- 正确:外部嵌套链接 -->
<a href="/back">
<svg class="icon-arrow">
<title>返回</title>
<use xlink:href="#icon-arrow"></use>
</svg>
</a>
或者使用 ARIA 规范中的 aria-label 属性:
html
<!-- 正确:使用 aria-label -->
<svg class="icon-arrow" aria-label="返回">
<title>返回</title>
<use xlink:href="#icon-arrow"></use>
</svg>
此时,辅助设备就会朗读"图像 返回"。
ARIA 规范属性
除原生的 HTML 元素和属性外,我们还可以用 ARIA 规范定义的 HTML 属性增强 Web 产品的无障碍访问能力。从功能上区分,这些属性可以分为三类:ARIA role 属性、ARIA 常规属性和 ARIA 状态属性。
ARIA role 属性
ARIA role 属性可以让没有语义的 HTML 元素变成有语义的元素。
alert 角色
表示重要的、且通常具有时效性的信息。
html
<p role="alert">图片上传失败</p>
alertdialog 角色
用于模态警告对话框。这类对话框会中断用户当前的工作流程,用于传达重要消息,并要求用户做出响应。
html
<div tabindex="0" role="alertdialog">
<p>弹出框</p>
<p>验证码已发送!</p>
<button>关闭</button>
</div>
application 角色
一个元素及其所有子元素应被视为类似桌面应用程序,并且不应使用传统的 HTML 解析技术进行处理。
html
<div id="application" role="application">
<label for="date">时间</label>
<input type="text" id="date">
<button>选择日期</button>
<div class="datepicker" aria-hidden="true">
<!-- 控件的具体内容 -->
</div>
</div>
article 角色
用于表示页面中的一个区块,该区块能够独立存在于页面、文档或网站中。
banner 地标角色
用于定义站点的头部。该区域通常包含徽标、公司名称、搜索功能,以及可能的全局导航或标语。
html
<div role="banner">
<img src="img/logo.png" alt="网站的logo">
<h1>网站名称</h1>
<nav></nav>
</div>
button 角色
用于表示可点击的元素,当用户激活该元素时会触发相应的响应行为。
html
<span role="button">点击我</span>
grid 角色
用于表示一个包含一行或多行单元格的小部件。每个单元格的位置都具有重要意义,并且可以通过键盘输入来聚焦选中。
treegrid 角色
用于标识一个元素为网格,其行可以像树形控件那样进行展开和折叠。
gridcell 角色
用于在网格或树形网格中创建一个单元格。它旨在模拟 HTML 的 <td> 元素的功能,用于对信息进行表格样式的分组。
table 角色
用于标识包含该角色的元素具有非交互式的表格结构,该结构包含按行和列排列的数据,类似于原生 HTML 的 <table> 元素。
cell 角色
用于将元素标识为表格容器中的单元格,该单元格不包含列头或行头信息。为了确保正确支持,该单元格必须嵌套在具有 row 角色的元素中。
row 角色
表格结构中的一行。在一行中,可以包含一个或多个单元格(Cell)、网格单元格(Gridcell)或列头(Column Header),以及可能的行头(Row Header)。该行存在于网格(Grid)、表格(Table)或树形网格(Treegrid)中,并且可选地存在于行组(Rowgroup)中。
rowgroup 角色
表格结构中的行组。一个行组包含一行或多行单元格(Cell)、网格单元格(Gridcell)、列头(Column Header)或行头(Row Header),这些行位于网格(Grid)、表格(Table)或树形网格(Treegrid)中。
rowheader 角色
一个单元格,包含网格(Grid)、表格(Table)或树形网格(Treegrid)的表格结构中某行的头信息。
columnheader 角色
用于将元素标识为行中的一个单元格,该单元格包含某一列的列头信息,类似于具有列范围的原生 <th> 元素。
html
<div role="table" aria-label="ARIA role 与语义元素对照表" aria-describedby="table_desc">
<div id="table_desc">建议优先使用语义元素,而不是 ARIA 的 role 属性</div>
<div role="rowgroup">
<div role="row">
<span role="columnheader">ARIA role 值</span>
<span role="columnheader">语义化元素</span>
<span role="columnheader">说明</span>
</div>
</div>
<div role="rowgroup">
<div role="row">
<span role="cell">button</span>
<span role="cell">button</span>
<span role="cell">可点击按钮</span>
</div>
<div role="row">
<span role="cell">link</span>
<span role="cell">a</span>
<span role="cell">超链接</span>
</div>
<div role="row">
<span role="cell">heading</span>
<span role="cell">h1-h6</span>
<span role="cell">标题</span>
</div>
<div role="row">
<span role="cell">navigation</span>
<span role="cell">nav</span>
<span role="cell">导航区域</span>
</div>
<div role="row">
<span role="cell">main</span>
<span role="cell">main</span>
<span role="cell">主要内容</span>
</div>
</div>
</div>
checkbox 角色
用于可勾选的交互式控件。包含 role="checkbox" 的元素还必须包含 aria-checked 属性,以向辅助技术暴露复选框的当前状态。
html
<ul role="group">
<li role="checkbox" aria-checked="mixed" tabindex="0">所有部门</li>
<li role="checkbox" aria-checked="false" tabindex="0">技术部</li>
<li role="checkbox" aria-checked="true" tabindex="0">设计部</li>
<li role="checkbox" aria-checked="true" tabindex="0">产品部</li>
</ul>
combobox 角色
用于将元素标识为输入框或按钮,该元素控制另一个可动态弹出的元素,以帮助用户设置值。
html
<div class="combobox-container">
<!-- 输入框:用户可输入或选择部门 -->
<input type="text" role="combobox" aria-autocomplete="inline" aria-owns="department-list" aria-expanded="true"
tabindex="0">
<span aria-hidden="true">▼</span>
<ul id="department-list" role="listbox" tabindex="-1" aria-expanded="true">
<li id="dept-1" role="option">技术部</li>
<li id="dept-2" role="option">设计部</li>
<li id="dept-3" role="option">产品部</li>
</ul>
</div>
command 角色
定义了一个执行操作但不接收输入数据的小部件。
comment 角色
表示对页面上某些内容的评论,或对先前评论的回复。
html
<div role="comment">
<div>张三</div>
<div><time datetime="2026-01-01T12:30">2026 年 1 月 1 日</time></div>
<p>评论内容</p>
</div>
complementary 地标角色
用于标识一个与主要内容相关、但单独分离时仍能独立存在的支撑性区域。这些区域通常以侧边栏或提示框的形式呈现。
html
<div role="complementary">
<h2>我们的合作伙伴</h2>
<!-- 补充区域内容 -->
</div>
contentinfo 地标角色
用于定义页脚区域,包含诸如版权信息、导航链接和隐私声明等标识性信息。
html
<div role="contentinfo">
<h2>页脚</h2>
<!-- 页脚内容 -->
</div>
definition 角色
表示该元素是一个术语或概念的定义。
html
<p>
<span role="term">HTML</span>
<span role="definition">HTML 超文本标记语言</span>
</p>
dialog 角色
用于标记基于 HTML 的应用程序对话框或窗口,该组件将内容或用户界面与 Web 应用或页面的其余部分隔离开。对话框通常通过遮罩层放置在页面其余内容的上方。
html
<div role="dialog" aria-labelledby="dialog1Title" aria-describedby="dialog1Desc">
<h2 id="dialog1Title">您的个人信息已成功更新</h2>
<p id="dialog1Desc">
您可以随时在用户账户部分更改您的信息。
</p>
<button>关闭</button>
</div>
document 角色
用于表示复杂复合小部件或应用程序中的可聚焦内容,辅助技术可以借此将阅读上下文切换回阅读模式。
html
<div role="dialog">
...
<div id="InfoText" role="document" tabindex="0">
<p>此处显示一些信息性文本。</p>
</div>
...
<button>关闭</button>
</div>
feed 角色
一个动态的可滚动文章列表,当用户滚动时,文章会从列表的任一端添加或移除。feed 使屏幕阅读器能够使用浏览模式的阅读光标,在富内容流中进行阅读和滚动;当用户阅读时,该列表可以通过加载更多内容无限滚动。
html
<section role="feed" aria-busy="false">
...
<article aria-posinset="427" aria-setsize="-1">...</article>
<article aria-posinset="428" aria-setsize="-1">...</article>
<article aria-posinset="429" aria-setsize="-1">...</article>
...
</section>
figure 角色
用于在页面内容中标识一个图形,适用于页面中尚不存在合适语义的情况。图形通常被认为包含一个或多个图像、代码片段或其他内容,这些内容以不同于常规文本流的方式传达信息。
html
<div role="figure" aria-labelledby="caption">
<img src="image.png" alt="在此处放置图片描述" />
<p id="caption">图 1:标题说明</p>
</div>
form 角色
用于标识页面上的一组元素,这些元素提供与 HTML 表单等同的功能。除非该表单具有可访问名称,否则它不会作为地标区域暴露给辅助技术。
html
<div role="form" id="contact-info" aria-label="联系信息">
<!-- 表单内容 -->
</div>
group 角色
用于标识一组用户界面对象,该组对象不应被辅助技术包含在页面摘要或目录中。
html
<div role="menu">
<ul role="group" aria-label="文件操作">
<li role="menuitem">新建</li>
<li role="menuitem">打开</li>
<li role="menuitem">保存</li>
</ul>
<ul role="group" aria-label="编辑操作">
<li role="menuitem">剪切</li>
<li role="menuitem">复制</li>
<li role="menuitem">粘贴</li>
</ul>
</div>
heading 角色
将该元素定义为页面或章节的标题,并通过 aria-level 属性提供更细致的结构层级。
html
<div role="heading" aria-level="2">章节标题</div>
img 角色
用于标识页面内容中应被视为单个图像的多个元素。这些元素可以是图像、代码片段、文本、表情符号或其他可以组合起来以视觉方式传递信息的内容。
html
<div role="img" aria-label="整体图像的描述">
<img src="graphic1.png" alt="日出">
<img src="graphic2.png" alt="黄昏">
</div>
link 角色
提供指向某个资源的交互式引用。目标资源可以是外部资源,也可以是本地资源。
html
<span data-href="https://mozilla.org" tabindex="0" role="link">
模拟链接
</span>
list 角色
用于标识一组项目列表。它通常与 listitem 配合使用。
html
<div role="list">
<div role="listitem">列表项 1</div>
<div role="listitem">列表项 2</div>
<div role="listitem">列表项 3</div>
</div>
listbox 角色
用于表示用户可从中选择一个或多个选项的列表。列表中的选项是静态的,并且与 HTML 的 <select> 元素不同,listbox 可以包含图像。
html
<p id="province-label">请选择省份:</p>
<div role="listbox" tabindex="0" id="province-list" aria-labelledby="province-label"
aria-activedescendant="province-1">
<div role="option" id="province-1" aria-selected="true">广东省</div>
<div role="option" id="province-2">江苏省</div>
<div role="option" id="province-3">浙江省</div>
<div role="option" id="province-4">四川省</div>
<div role="option" id="province-5">湖北省</div>
</div>
listitem 角色
用于标识列表中的一个项目。它通常与 list 配合使用。
log 角色
用于标识一个元素,该元素创建一个实时区域,其中新信息按照有意义的顺序添加,旧信息可能会消失。
html
<!-- 聊天消息容器 -->
<div role="log" aria-atomic="false" aria-relevant="additions" id="chat-history">
<!-- 初始已有消息 -->
<p>用户A: 你好</p>
<p>用户B: 嗨!</p>
</div>
main 地标角色
用于标识文档的主要内容。主要内容区域由与文档中心主题直接相关、对中心主题进行展开阐述或与应用主要功能相关的内容构成。
html
<div id="main" role="main">
<h1>牛油果</h1>
<!-- 主要内容区域内容 -->
</div>
mark 角色
用于表示因在所在上下文中具有相关性而被标记或高亮以供参考或注释的内容。
html
<p>
无障碍访问是 Web 开发中<span role="mark">非常重要</span>的一环,它能让更多用户正常使用你的产品。
</p>
marquee 角色
一种实时区域,包含非必要的、频繁变化的信息。
html
<!-- 股票行情滚动区域 -->
<div role="marquee" aria-label="实时股票行情">
<p>Goosoft $8.24 +0.36</p>
<p>Microle $35.60 −0.78</p>
<p>Banana $12.30 +0.09</p>
</div>
math 角色
用于标识包含数学公式或表达式的元素。
html
<div role="math" aria-label="a^{2} + b^{2} = c^{2}">
a<sup>2</sup> + b<sup>2</sup> = c<sup>2</sup>
</div>
menu 角色
一种复合组件,用于向用户提供一系列可选项。
menubar 角色
一种菜单的呈现形式,通常保持可见,并且通常以水平方式呈现。
menuitem 角色
表示元素是包含在菜单(menu)或菜单栏(menubar)中的一组选项里的一个可选项。
menuitemcheckbox 角色
一个带有可选中状态的菜单项,其可选值为 true、false 或 mixed。
menuitemradio 角色
一个可选中的菜单项,它属于一组具有相同角色的元素集合,且在同一时间该集合中只能有一个元素被选中。
html
<ul role="menubar" aria-label="主菜单">
<li role="menuitem" tabindex="0" aria-haspopup="true">文件
<ul role="menu" aria-hidden="true">
<li role="menuitemradio" tabindex="-1">新建</li>
<li role="menuitemradio" tabindex="-1">打开</li>
<li role="menuitemradio" tabindex="-1" aria-haspopup="true">另存为
<ul role="menu" aria-hidden="true">
<li role="menuitemradio" tabindex="-1">PDF</li>
<li role="menuitemradio" tabindex="-1">Word</li>
<li role="menuitemradio" tabindex="-1">文本</li>
</ul>
</li>
<li role="menuitemradio" tabindex="-1">退出</li>
</ul>
</li>
<li role="menuitem" tabindex="-1" aria-haspopup="false">编辑</li>
<li role="menuitem" tabindex="-1" aria-haspopup="false">视图</li>
</ul>
meter 角色
用于标识用作度量盘的元素。
html
<div role="meter" aria-valuenow="90" aria-valuemin="0" aria-valuemax="100" aria-labelledby="cpu_usage_label">
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" style="width: 90%">
<rect x="0" y="0" width="100%" height="100%" fill="currentColor"></rect>
</svg>
</div>
navigation 地标角色
用于标识一组主要链接,这些链接用于在网站或页面内容中进行导航。
html
<div role="navigation" aria-label="Main">
<!-- 指向网站主要页面的链接列表 -->
</div>
none 角色
presentation 角色的同义词;两者都会移除元素隐式具有的 ARIA 语义,使其不暴露给无障碍树。
html
<hr role="none">
note 角色
表示一个章节,其内容相对于主要内容而言是插入性的或辅助性的。
html
<!-- 注释/提示信息 -->
<div role="note" aria-label="使用说明">
<p>请确保在提交前填写所有必填字段。</p>
</div>
option 角色
用于列表框中的可选项。
html
<ul role="listbox" tabindex="-1" aria-expanded="true">
<li role="option">技术部</li>
<li role="option">设计部</li>
<li role="option">产品部</li>
</ul>
presentation 角色
会移除元素隐式具有的 ARIA 语义,使其不暴露给无障碍树。
html
<h2 role="presentation">温故知新</h2>
progressbar 角色
定义了一个用于显示耗时任务进度的元素。
html
<div>
<span id="loadinglabel">加载中:</span>
<span role="progressbar" aria-labelledby="loadinglabel" aria-valuenow="23">
<svg width="100" height="10">
<rect height="10" width="100" stroke="black" fill="black" />
<rect height="10" width="23" fill="white" />
</svg>
</span>
</div>
radiogroup 角色
一组单选按钮的集合。
radio 角色
一组可选中单选按钮中的一个,位于单选按钮组中,且同一时间只能有一个单选按钮被选中。
html
<div role="radiogroup" aria-labelledby="payment-question">
<div id="payment-question">请选择支付方式:</div>
<div id="payment-options">
<p>
<span id="payment_0" tabindex="0" role="radio" aria-checked="true" aria-labelledby="wechat"></span>
<span id="wechat">微信支付</span>
</p>
<p>
<span id="payment_1" tabindex="-1" role="radio" aria-checked="false" aria-labelledby="alipay"></span>
<span id="alipay">支付宝</span>
</p>
<p>
<span id="payment_2" tabindex="-1" role="radio" aria-checked="false" aria-labelledby="card"></span>
<span id="card">银行卡</span>
</p>
<p>
<span id="payment_3" tabindex="-1" role="radio" aria-checked="false" aria-labelledby="cash"></span>
<span id="cash">现金支付</span>
</p>
</div>
</div>
region 地标角色
用于标识作者认为重要的文档区域。
html
<div role="region" aria-label="示例区域">
<!-- 区域内容 -->
</div>
scrollbar 角色
一个图形化对象,用于控制内容在可视区域内的滚动。
html
<div id="pi-label">圆周率</div>
<div id="pi">
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
</div>
<div
role="scrollbar"
aria-labelledby="pi-label"
aria-controls="pi"
aria-orientation="horizontal"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100">
<div id="thumb"></div>
</div>
search 地标角色
用于标识搜索功能区域。
html
<form role="search">
<!-- 搜索输入框 -->
</form>
searchbox 角色
表示搜索输入框。
html
<div tabindex="0" aria-label="search" role="searchbox" contenteditable></div>
separator 角色
用于分隔和区分不同的内容区域或菜单项组。
html
<!-- 菜单中的分割线 -->
<ul role="menu">
<li role="menuitem">复制</li>
<li role="menuitem">粘贴</li>
<li role="separator"></li>
<li role="menuitem">删除</li>
<li role="menuitem">重命名</li>
</ul>
slider 角色
定义了一个输入控件,用户可以在给定范围内从中选择一个值。
html
<!-- 简单的音量滑块 -->
<div id="volume-label">音量</div>
<div role="slider"
aria-labelledby="volume-label"
aria-valuenow="50"
aria-valuemin="0"
aria-valuemax="100"
tabindex="0">
</div>
<span id="volume-value">50%</span>
spinbutton 角色
定义了一种范围类型,期望用户从一系列离散选项中选择一个值。
html
<p id="age-label">选择年龄</p>
<button type="button" tabindex="-1" aria-label="减少年龄">−</button>
<div role="spinbutton"
tabindex="0"
aria-valuenow="25"
aria-valuetext="二十五岁"
aria-valuemin="0"
aria-valuemax="120"
aria-labelledby="age-label"
style="display: inline-block; width: 50px; text-align: center;">
25
</div>
<button type="button" tabindex="-1" aria-label="增加年龄">+</button>
<span>岁</span>
status 角色
定义了一个实时区域,其中包含向用户提供的建议性信息,这些信息的重要程度不足以成为警告。
html
<div role="status" aria-live="polite">
数据加载完成,共找到 12 条结果
</div>
suggestion 角色
表示对可编辑文档的单个建议更改。该元素内应包含一个带有 insertion 角色的元素和一个带有 deletion 角色的元素。
html
<p>
弗里达的宠物是一只
<span role="suggestion">
<span role="deletion">名叫 Luna 的黑猫</span>
<span role="insertion">名叫 Tiny 的紫色霸王龙</span>
</span>。
</p>
switch 角色
在功能上与 checkbox 角色完全相同,区别在于 checkbox 表示语义较为通用的「已选中」和「未选中」状态,而 switch 角色则表示「开」和「关」状态。
html
<button type="button" role="switch" aria-checked="true" id="speakerPower">
<span aria-hidden="true">关</span>
<span aria-hidden="false">开</span>
</button>
<label for="speakerPower" class="switch">扬声器电源</label>
tablist 角色
用于标识作为一组选项卡容器的元素。
tab 角色
表示选项卡列表(tablist)内部的一个交互式元素,当该元素被激活时,会显示其关联的选项卡面板(tabpanel)。
tabpanel 角色
用于存放与某个选项卡相关联的分层内容资源。
html
<div>
<ul role="tablist">
<li aria-selected="true" role="tab" tabindex="0">商品描述</li>
<li aria-selected="false" role="tab" tabindex="-1">规格参数</li>
<li aria-selected="false" role="tab" tabindex="-1">用户评价</li>
</ul>
<div id="panel1" role="tabpanel">商品描述内容...</div>
<div id="panel2" role="tabpanel">规格参数内容...</div>
<div id="panel3" role="tabpanel">用户评价内容...</div>
</div>
term 角色
用于表示一个词或短语,并可选地附带对应的定义。
html
<p>
<span role="term">FOMO</span>,
<span role="definition">错失恐惧症,指因担心错过他人的有益经历或事件而产生的焦虑感</span>。
</p>
textbox 角色
用于标识允许输入自由格式文本的元素。
html
<div role="textbox" contenteditable="true" aria-label="评论输入框" aria-multiline="true" tabindex="0">
请输入您的评论...
</div>
timer 角色
一个数值计数器,用于列出从起点开始经过的时间量或距离终点剩余的时长。
html
<div role="timer" aria-label="倒计时">
<span>00</span>
<span>00</span>
<span>00</span>
</div>
toolbar 角色
一组常用功能按钮或控件的集合,这些按钮或控件以紧凑的视觉形式呈现。
html
<div role="toolbar" aria-label="文本编辑工具栏">
<button>加粗</button>
<button>倾斜</button>
<button>下划线</button>
</div>
tooltip 角色
一个上下文相关的文本气泡,用于在指针悬停或键盘聚焦时显示某个元素的描述信息。
html
<button id="save-btn" aria-describedby="save-tip">保存</button>
<div role="tooltip" id="save-tip">保存当前文档(Ctrl+S)</div>
ARIA 常规属性
这些属性提供关于元素的额外信息,帮助辅助技术(如屏幕阅读器)更好地理解内容。
aria-activedescendant
用于当焦点位于复合组件(composite widget)、组合框(combobox)、文本框(textbox)、分组(group)或应用程序(application)上时,标识当前活动的元素。
该属性的值为当前获得焦点的元素的 id。
html
<div role="toolbar" tabindex="0" aria-activedescendant="button1">
<img src="btncut.png" role="button" id="button1" alt="cut">
<img src="btncopy.png" role="button" id="button2" alt="copy">
<img src="btnpaste.png" role="button" id="button3" alt="paste">
</div>
aria-atomic
一个全局 ARIA 状态,指示辅助技术是基于 aria-relevant 属性定义的变更通知来呈现整个变更区域,还是仅呈现该区域的部分内容。
false:默认值,仅呈现发生变更的节点或节点集合。true:将整个变更区域作为一个整体进行呈现,如果存在开发者定义的标签,则一并呈现该标签。
html
<div role="heading" aria-live="assertive" aria-atomic="true">
订单状态:已发货
</div>
aria-autocomplete
指示输入文本时是否会触发显示针对组合框(combobox)、搜索框(searchbox)或文本框(textbox)中用户预期取值的一个或多个预测结果,并指定这些预测结果的呈现方式。
none:当用户进行输入时,不显示任何自动建议。inline:在插入符后方可动态插入用于补全用户已输入内容的建议文本。list:当用户进行输入时,可显示一个包含若干候选值的元素,这些候选值可用于补全用户已输入的内容。both:输入框同时提供上述两种模式。当用户进行输入时,可显示一个包含若干候选值的元素,这些候选值可用于补全用户已输入的内容。如果显示了候选值集合,则其中某个值会被自动选中,且补全该自动选中值所需的文本将出现在输入框中的插入符后方。
html
<label id="tag-label">添加标签:</label>
<input type="text"
id="tag-input"
role="combobox"
aria-autocomplete="both"
aria-expanded="false"
aria-controls="tag-list"
aria-labelledby="tag-label"
placeholder="输入标签">
<ul id="tag-list" role="listbox" hidden>
<li role="option">JavaScript</li>
<li role="option">Python</li>
<li role="option">HTML</li>
<li role="option">CSS</li>
<li role="option">React</li>
</ul>
<div id="inline-preview"></div>
需要注意的是,如果 aria-autocomplete="Iist/inline/both" 被设置在支持 autocomplete 的元素上,则 autocomplete 属性值需要被设置为 on;如果是 aria-autocomplete="none",则需要被设置为 off。
aria-busy
一个全局 ARIA 状态,用于指示某个元素当前是否正在被修改。
false:默认值,该元素没有预期的更新。true:该元素正在被更新中。
html
<div aria-busy="true" aria-live="polite" aria-label="内容加载中">
<span>加载中...</span>
</div>
aria-controls
一个全局属性,用于建立元素之间的控制关系,指明当前元素控制或影响另一个元素。
值:一个或多个元素的 ID(空格分隔)
html
<div role="tablist">
<div role="tab" tabindex="0" aria-selected="true" aria-controls="panel-1">概览</div>
<div role="tab" tabindex="-1" aria-selected="false" aria-controls="panel-2">详情</div>
<div role="tab" tabindex="-1" aria-selected="false" aria-controls="panel-3">设置</div>
</div>
<div role="tabpanel" id="panel-1">
<p>概览面板内容</p>
</div>
<div role="tabpanel" id="panel-2" hidden>
<p>详情面板内容</p>
</div>
<div role="tabpanel" id="panel-3" hidden>
<p>设置面板内容</p>
</div>
aria-current
元素上非空的 aria-current 状态表示该元素代表当前容器或相关元素集合中的当前项。
page:表示一组页面中的当前页面。step:表示一个流程中的当前步骤。location:表示环境或上下文中的当前位置。date:表示一组日期中的当前日期。time:表示一组时间中的当前时间。true:表示一组项目中的当前项目。false:不表示一组项目中的当前项目。
html
<ol aria-label="注册步骤">
<li aria-current="step">填写信息</li>
<li>验证手机</li>
<li>完成注册</li>
</ol>
aria-describedby
全局属性,用于将某个元素与提供额外描述信息的另一个元素关联起来,辅助技术会在朗读主标签后,追加朗读描述内容。
值:一个或多个描述当前元素的元素的 id,多个 id 之间使用空格分隔。
html
<label for="password">密码</label>
<input
type="password"
id="password"
aria-describedby="password-hint"
>
<span id="password-hint">
密码长度至少8位,需包含字母和数字
</span>
aria-description
全局属性,用于为元素提供额外的描述性文本。
值:一个字符串。
html
<div role="tree" aria-label="文件目录" aria-description="使用上下箭头键移动,右箭头展开文件夹,左箭头折叠,回车键打开文件">
<div role="treeitem">文档</div>
<div role="treeitem">图片</div>
</div>
aria-details
全局属性,用于指向提供详细补充信息的元素。
值:一个或多个提供或链接到附加相关信息的元素的 id,多个 id 之间使用空格分隔。
html
<label for="tax-id">纳税人识别号</label>
<input type="text" id="tax-id" aria-details="tax-help">
<div id="tax-help">
<h4>填写说明</h4>
<ul>
<li>企业用户:填写18位统一社会信用代码</li>
<li>个人用户:填写18位身份证号码</li>
<li>外资企业:填写9位组织机构代码</li>
</ul>
<p>如有疑问,请联系客服:<a href="tel:4001234567">400-123-4567</a></p>
</div>
aria-flowto
全局属性,用于自定义屏幕阅读器的阅读顺序,打破 DOM 顺序的默认限制,将用户导航引导至指定的下一个元素。
id:替代阅读顺序中下一个元素的id。id列表:一个空格分隔的列表,包含一个或多个元素的id值。
html
<div role="region" aria-label="注册向导">
<div id="step1" aria-flowto="step2">
<h2>步骤一:填写基本信息</h2>
<input type="text" aria-label="姓名">
</div>
<div id="step2" aria-flowto="step3">
<h2>步骤二:验证手机号</h2>
<input type="tel" aria-label="手机号">
</div>
<div id="step3">
<h2>步骤三:完成注册</h2>
<button>提交</button>
</div>
</div>
aria-haspopup
表示当前区域是否有弹出框。
false:默认值,该元素没有弹出元素。true:弹出元素是一个菜单。menu:弹出元素是一个菜单。listbox:弹出元素是一个列表框。tree:弹出元素是一个树。grid:弹出元素是一个网格。dialog:弹出元素是一个对话框。
html
<button aria-haspopup="menu" aria-expanded="false" aria-controls="user-menu">
用户中心
</button>
<ul id="user-menu" role="menu" hidden>
<li role="menuitem">个人资料</li>
<li role="menuitem">账号设置</li>
<li role="menuitem">退出登录</li>
</ul>
aria-keyshortcuts
用于声明元素可用的键盘快捷键,帮助辅助技术用户发现和了解快捷操作方式。
值:一个空格分隔的键盘组合键列表,当按下这些组合键时,将执行相应的操作。
html
<div role="toolbar" aria-label="文本格式">
<button aria-keyshortcuts="Ctrl+B Meta+B" aria-pressed="false">
粗体
</button>
<button aria-keyshortcuts="Ctrl+I Meta+I" aria-pressed="false">
斜体
</button>
<button aria-keyshortcuts="Ctrl+U Meta+U" aria-pressed="false">
下划线
</button>
<button aria-keyshortcuts="Ctrl+K Meta+K">
插入链接
</button>
</div>
aria-label
用于为元素提供不可见的文本标签,覆盖元素原有的可访问名称,供辅助技术(如屏幕阅读器)朗读。
值:一段文本字符串,将作为该对象的无障碍名称。
html
<input type="search" aria-label="搜索商品">
aria-labelledby
用于引用页面上其他可见元素的文本内容作为当前元素的标签,建立元素之间的标签关联关系。
值:一个空格分隔的列表,包含一个或多个 ID 值,这些 ID 引用了为当前元素提供标签的元素。
html
<span
role="checkbox"
aria-checked="false"
tabindex="0"
aria-labelledby="tac"></span>
<span id="tac">我同意当前用户协议</span>
优先级:
aria-labelledby > aria-label > 原生 HTML 标签 > aria-placeholder > ...
aria-level
用于定义元素在结构中的层级。
值:一个大于或等于 1 的整数。
html
<div role="heading" aria-level="3">三级标题</div>
aria-live
全局属性,指示某个元素将会被更新,并描述用户代理、辅助技术以及用户可以预期从该实时区域接收到的更新类型。
assertive:指示对该区域的更新具有最高优先级,并应立即呈现给用户。off:默认值,指示除非用户当前正聚焦于该区域,否则不应向用户呈现该区域的更新。polite:指示应在下一个适当的时机呈现对该区域的更新。
html
<div id="announce" aria-live="polite">
<p>此消息会被播报。</p>
</div>
aria-modal
用于指示一个对话框或模态框是否模态化。
false:默认值,元素不是模态的。true:元素是模态的。
html
<div role="dialog"
aria-modal="true"
aria-labelledby="dialog-title"
aria-describedby="dialog-desc">
<h2 id="dialog-title">确认删除</h2>
<p id="dialog-desc">删除后数据无法恢复,是否继续?</p>
<button>取消</button>
<button>确认删除</button>
</div>
aria-multiline
用于指示文本输入框是否支持多行输入,帮助辅助技术正确识别编辑区域的类型和行为。
true:文本框接受多行输入。false:文本框仅接受单行输入。
html
<div role="textbox"
aria-multiline="true"
aria-label="评论内容"
aria-placeholder="请输入您的评论..."
contenteditable="true">
</div>
aria-multiselectable
用于指示一个列表或网格是否支持同时选择多个项目,告知辅助技术用户该选择控件的类型和行为。
true:该 widget 中同一时间可以有多个项目被选中。false:只能有一个项目被选中。
html
<div role="listbox"
aria-multiselectable="true"
aria-label="选择技能标签"
aria-describedby="selection-hint">
<div role="option" aria-selected="false">JavaScript</div>
<div role="option" aria-selected="true">React</div>
<div role="option" aria-selected="false">Vue</div>
<div role="option" aria-selected="true">Node.js</div>
</div>
<p id="selection-hint">按住 Ctrl 键可多选</p>
aria-orientation
用于指示组件的方向或排列方式,告知辅助技术用户该控件是水平还是垂直布局。
horizontal:水平方向排列。vertical:垂直方向排列undefined:默认值,方向不明确或未知。
html
<div role="slider"
aria-orientation="vertical"
aria-label="音量控制"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="50"
aria-valuetext="50%">
</div>
aria-owns
用于在无法使用 DOM 层级结构来表示父子关系时,标识一个或多个元素,从而定义父元素与子元素之间的视觉、功能或上下文关系。
值:一个空格分隔的列表,包含一个或多个 ID 值,这些 ID 引用了被当前元素所拥有的元素。
html
<!-- 菜单按钮在导航栏内,但菜单面板需要出现在页面其他位置 -->
<nav>
<button aria-haspopup="menu" aria-controls="user-menu" aria-expanded="false">
用户菜单
</button>
</nav>
<!-- 菜单面板实际位于页面底部,但通过 aria-owns 建立逻辑关系 -->
<div id="user-menu" role="menu" hidden>
<div role="menuitem">个人资料</div>
<div role="menuitem">设置</div>
<div role="menuitem">退出</div>
</div>
<!-- 在按钮上声明所有权 -->
<button aria-haspopup="menu" aria-owns="user-menu" aria-expanded="false">
用户菜单
</button>
aria-placeholder
用于为输入框提供提示文本,描述预期的输入值格式或示例。
值:在控件没有值时,显示于该控件中的单词或短句。
html
<div role="textbox"
aria-label="出生日期"
aria-placeholder="YYYY-MM-DD 格式,例如 1990-05-20"
contenteditable="true">
</div>
aria-posinset
用于指示元素在集合中的当前位置序号,帮助辅助技术用户了解当前项在整体列表中的位置。
值:整数,从 1 开始计数
html
<div role="list" aria-label="商品列表" aria-setsize="1000" aria-busy="false">
<div role="listitem" aria-posinset="1" aria-setsize="1000">
商品 1
</div>
<div role="listitem" aria-posinset="2" aria-setsize="1000">
商品 2
</div>
<div role="listitem" aria-posinset="3" aria-setsize="1000">
商品 3
</div>
<!-- 实际 DOM 中只有 3 项,但用户知道总共有 1000 项 -->
</div>
aria-relevant
用于指示实时区域中哪些类型的内容变化应该通知辅助技术用户,控制屏幕阅读器何时打断用户当前操作进行播报。
additions:默认值,节点添加到实时区域时通知。removals:节点从实时区域移除时通知。text:文本内容变化时通知。all:所有变化都通知。
html
<div role="log"
aria-live="polite"
aria-relevant="additions"
aria-atomic="false"
aria-label="聊天记录">
<div>张三:大家好</div>
<div>李四:你好</div>
<!-- 新消息插入时通知,旧消息删除不通知 -->
</div>
aria-roledescription
用于自定义或覆盖元素的默认角色描述,让辅助技术用更具体、更贴合场景的词汇来描述组件功能。
值: 纯文本字符串。
html
<div role="region"
aria-roledescription="轮播"
aria-label="热门推荐">
<button aria-label="上一张">‹</button>
<img src="slide1.jpg" alt="产品展示">
<button aria-label="下一张">›</button>
</div>
aria-setsize
用于指示集合中项目的总数,帮助辅助技术用户了解整体规模,通常与 aria-posinset 配合使用。
值:完整集合中的项目数量;如果集合大小未知,则为 -1。
html
<div role="list" aria-label="搜索结果" aria-setsize="256">
<div role="listitem" aria-posinset="1" aria-setsize="256">结果 1</div>
<div role="listitem" aria-posinset="2" aria-setsize="256">结果 2</div>
<div role="listitem" aria-posinset="3" aria-setsize="256">结果 3</div>
<!-- 当前只显示 3 项,但用户知道总共有 256 项 -->
</div>
<p>显示 3/256 条结果</p>
aria-sort
用于指示表格或网格列的当前排序状态,告知辅助技术用户该列是否已排序及排序方向。
none:默认值,未排序。ascending:升序排列(A-Z,1-9)。descending:降序排列(Z-A,9-1)。other:其他排序方式。
html
<table role="grid" aria-label="销售数据">
<thead>
<tr>
<th role="columnheader" aria-sort="none">产品名称</th>
<th role="columnheader" aria-sort="ascending" aria-label="销售额,升序排列">
销售额 ▲
</th>
<th role="columnheader" aria-sort="none">日期</th>
</tr>
</thead>
<tbody>
<tr><td>产品A</td><td>120万</td><td>2026-04-01</td></tr>
<tr><td>产品B</td><td>150万</td><td>2026-04-02</td></tr>
</tbody>
</table>
aria-valuemax、aria-valuemin、aria-valuenow、aria-valuetext
aria-valuemin:允许的最小值。aria-valuemax:允许的最大值。aria-valuenow:必须,当前数值。aria-valuetext:当前值的可读文本描述。
html
<div role="slider"
aria-label="音量控制"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="65"
aria-valuetext="65%"
tabindex="0">
</div>
ARIA 状态属性
值都为 true 或 false。
| ARIA 状态属性 | 描述 |
|---|---|
aria-hidden |
表示当前区域是否被隐藏 |
aria-invalid |
表示当前区域是否无效 |
aria-pressed |
表示当前区域是否被按下 |
aria-readonly |
表示当前区域是否只读 |
aria-required |
表示当前区域是否必填 |
aria-selected |
表示当前区域是否被选中 |
aria-checked |
表示当前区域是否被选中 |
aria-disabled |
表示当前区域是否被禁用 |
aria-expanded |
表示当前区域是否被展开 |