aria-label仅在元素无可见文本且无法用原生语义替代时必须使用,如纯图标按钮、仅含emoji控件、动态spinner、自定义开关根节点;禁用于已有可见文本或原生语义的元素,否则覆盖真实内容。

aria-label 不是“给元素加个描述”这么简单,它只在元素真没可见文本、又必须被屏幕阅读器识别时才该用;加错位置或滥用,反而会让内容对视障用户彻底消失。
哪些元素必须加 aria-label?
只有当元素本身没有可读的可见文本,且无法靠原生语义补救时,aria-label 才是必要手段:
-
<button></button>里只有<svg></svg>或图标字体(如<i class="icon-close"></i>),必须加aria-label="关闭" - 自定义
<div role="button"> 或 <code><span role="link"></span>,没文字就等于没名字,不加aria-label就会被读作“按钮”或“链接”,功能全无 - 动态生成的加载状态容器,比如
<div class="spinner" role="status"></div>,需配aria-label="加载中"让状态可感知 - 纯 Emoji 控件:
<div role="button" tabindex="0">?</div>,Emoji 不被读屏器识别为有效文本,必须靠aria-label="搜索" - 给
<img>加aria-label:错误!必须用alt,二者语义冲突,可能触发重复朗读或跳过图像 - 给已有
<label for="email">邮箱地址</label>的<input id="email">再加aria-label:Lighthouse 直接报错,label的语义被绕过,焦点管理与语音控制都会出问题 - 给普通
<div> 或 <code><span></span>加aria-label:无效!它们默认不可聚焦、无交互角色,读屏器通常直接跳过;若硬要让它可读,得同时加role="button"和tabindex="0",但这暴露的是设计缺陷,不是补救方案 -
aria-label=""(空字符串):等于告诉读屏器“这个可操作元素无需朗读”,相当于把交互入口对视障用户彻底封死 - 有——用
aria-labelledby,指向那个元素的id。例如:<h2 id="chart-title">月度销售额</h2>+<canvas aria-labelledby="chart-title"></canvas>。文案改了、翻译切了,读屏内容自动同步 - 没有——才用
aria-label,比如关闭弹窗的 × 按钮、仅含 SVG 的返回图标 - 两者不能共存:
aria-labelledby优先级高于aria-label,写了也白写 - 别指望
placeholder替代:placeholder="请输入邮箱"不是标签,输入后就消失,且部分读屏器根本不识别它 - ID 拼错、目标元素被
display: none或aria-hidden="true"隐藏 →aria-labelledby引用失败,整个控件对读屏器失联 - 多个 ID 必须用空格分隔:
aria-labelledby="title desc",写成aria-labelledby="title,desc"或连写会失效 - NVDA 在鼠标悬停时不读
aria-label—— 它只在键盘焦点(Tab 进入)时触发,这是设计使然,不是 bug - 中文文案避免拼音缩写或网络用语:
aria-label="点我"不如aria-label="开始上传"明确,尤其对老年或非母语用户 - 动态切换状态时(如静音/取消静音),必须同步更新
aria-label值,并配合aria-pressed或aria-expanded等状态属性
哪些地方加了反而破坏无障碍?
aria-label 会完全覆盖元素内所有文本,包括子节点内容。很多失效不是没写,而是写在了不该写的地方:
aria-label 和 aria-labelledby 怎么选?
核心判断标准就一个:页面上有没有现成的、可见的、可访问的文本?
容易被忽略的细节和验证方式
最常出问题的地方不在“加没加”,而在“加得对不对”:











