aria-label是为无可见文本的可交互元素提供屏幕阅读器可读名称的底线要求,必须加在等容器上而非内,有现成文本时应优先用aria-labelledby引用。

aria-label 不是装饰性补丁,是给没文字的可交互元素“起名字”的底线要求。没它,屏幕阅读器只读“按钮”“链接”,用户根本不知道点它会干什么。
纯图标按钮必须加 aria-label,且写在 <button></button> 上
常见错误是把 aria-label 塞进 <svg></svg> 或 <i></i> 里——读屏器完全不认。它只认可聚焦、可交互的容器。
- ✅ 正确:
<button aria-label="删除"><svg aria-hidden="true"></svg></button> - ❌ 错误:
<button><svg aria-label="删除" aria-hidden="true"></svg></button>(aria-label被忽略) -
<svg></svg>必须同步加aria-hidden="true",否则某些读屏器可能误读路径描述,造成干扰 - 模态框右上角 × 按钮、树形组件折叠图标、筛选清空按钮,都属于这类刚性场景
aria-label 和 aria-labelledby 到底用哪个?看页面有没有现成文本
判断标准就一条:元素附近有没有**可见、语义匹配、可访问**的文本节点?有,就用 aria-labelledby;没有,才硬编码 aria-label。
- ✅ 用
aria-labelledby:<h2 id="modal-title">编辑用户</h2>+<button aria-labelledby="modal-title"><svg></svg></button>(文案更新、多语言切换自动生效) - ✅ 用
aria-label:关闭按钮、下载图标、加载 spinner,这些地方真没现成文本可引用 - ⚠️ 两者共存 →
aria-labelledby优先级更高,aria-label静默失效;Lighthouse 和 axe 都会报错 -
aria-labelledby支持空格分隔多个 ID:aria-labelledby="icon-desc name-cell",读屏器按顺序拼接朗读
哪些地方加了 aria-label 反而坏事?
滥用比不加更危险——它会直接覆盖原生语义,让屏幕阅读器“听不见真实内容”。
- ❌ 给
<img>加aria-label:应始终用alt;混用可能导致重复朗读或图像被跳过 - ❌ 给已有
<label for="xxx"></label>的<input>再加aria-label:绕过表单语义,语音控制、焦点管理、验证全失效 - ❌ 给
<button>导出 PDF</button>加aria-label="下载文件":覆盖可见文本,导致视听不一致 - ❌
aria-label="":等于告诉读屏器“这个元素无需朗读”,但若它实际可点击,就等于对视障用户彻底隐藏交互入口 - ❌ 给
<h2></h2>、<nav></nav>、<table> 这类原生语义元素硬加:Nu HTML Checker 会警告 “Possible misuse of aria-label” <h3>面包屑、导航等区域级容器怎么用 <code>aria-label?不是所有
aria-label都用来补按钮,有些是为整块区域定性,比如区分多个<nav></nav>。- ✅ 面包屑必须用
<nav aria-label="面包屑导航"></nav>包裹(中文可用,NVDA + Chrome 支持稳定) - ❌ 不能写成
aria-label="Navigation"或省略——前者太泛,后者让读屏器无法区分主导航和路径导航 -
<nav></nav>内部必须用<ol><li></ol>结构,aria-current="page"加在当前页<li>上,不是aria-disabled - 分隔符(如
/或>)要用aria-hidden="true"或伪元素实现,避免被读出
最常出问题的地方不在“加没加”,而在“加得对不对”:ID 拼错、目标元素被
display: none或aria-hidden="true"隐藏、值为空字符串、写在非交互元素上——这些都会让可访问名称彻底失效,且调试时往往无声无息。 - ✅ 面包屑必须用
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











