aria-label是wcag 4.1.2强制要求,用于无可见文本的按钮(如纯图标、关闭按钮、svg内嵌按钮),必须加在可交互元素上并配aria-hidden="true"于svg内部,不可为空或冗余覆盖真实文本。

按钮没文字时必须加 aria-label
纯图标按钮、× 关闭按钮、SVG 内嵌按钮,只要内部没有可读的可见文本,aria-label 就不是“可选”,而是 WCAG 4.1.2 强制要求。不加的结果是屏幕阅读器只读“按钮”,用户完全不知道点它会触发什么操作。
-
aria-label必须写在可交互容器上(如<button></button>),不能只加在<svg></svg>或<i></i>里——加了也无效 -
<svg></svg>内部要同步加aria-hidden="true",否则部分读屏器可能误读路径描述 - 值不能为空字符串:
aria-label=""会让该按钮对辅助技术彻底不可见 - 中文文案需简洁明确,避免“点击此处”“操作按钮”这类无意义描述,应写成
aria-label="删除第3条消息"这类具体语义
aria-label 和 aria-labelledby 到底用哪个?
核心判断标准就一条:页面上有没有现成的、可见的、可访问的文本?有,就用 aria-labelledby;没有,才用 aria-label。
- 图标旁已有文字“设置”,就该用
aria-labelledby="setting-label",而不是硬编码aria-label="设置"——后者会导致多语言或文案更新后失效 - 表格每行的“编辑”按钮,label 来自该行姓名单元格(
id="name-123"),就写aria-labelledby="name-123" - 两者绝不能共存:
aria-label优先级更高,会直接覆盖aria-labelledby,Lighthouse 和 axe 都会报错 -
aria-labelledby支持空格分隔多个 ID:aria-labelledby="icon desc input",适合组合式上下文
哪些地方加了 aria-label 反而破坏无障碍?
最常出问题的不是“没加”,而是“加错位置”或“覆盖真实内容”。一旦写错,用户听到的就不是你期望的内容。
-
<button aria-label="提交">发送</button>→ 屏幕阅读器只读“提交”,“发送”被静音 -
<input>已有<label for="email">邮箱地址</label>,再加aria-label属于冗余,Lighthouse 直接报错 - 给
<div> 或 <code><span></span>这类非交互元素单独加aria-label—— 它们默认不可聚焦,读屏器通常不读;非要这么做,得同时加role="button"和tabindex="0",但这暴露了语义缺陷,不如直接换<button></button> - 多语言站点把
aria-label写死成英文,比如aria-label="Close",后续翻译系统无法同步更新 -
title只在鼠标悬停时显示 tooltip,多数屏幕阅读器默认不读,移动端几乎不触发 -
placeholder="请输入邮箱"输入后就消失,且部分读屏器根本不识别它,不能替代<label></label> - 用
<input type="button" value="删除">看似有文字,但中文空格或省略号(如value="")会导致信息丢失,优先改用<button></button>+ 显式文本或aria-label - 禁用状态按钮(
disabled)屏幕阅读器会自动跳过,但用pointer-events: none模拟禁用,反而让按钮“可读不可用”,这是高频坑
为什么不用 title 或 placeholder 替代?
title 不是无障碍标签,placeholder 更不是。它们对键盘和语音用户基本无效。
aria-label,而是判断“这个按钮到底有没有可见文本”——视觉设计师可能用 CSS 隐藏文字、用伪元素生成图标、或把文字放在父容器里,这些都会让“可见性”变得模糊。每次加之前,先用键盘 Tab 焦点进入,再开 VoiceOver 或 NVDA 听一遍,比看代码更可靠。











