aria-label 比 title 更可靠,因阅读器优先读取 aria-label 且其显式声明可覆盖默认无障碍名称,而 title 仅作悬浮提示、不参与无障碍树构建。

aria-label 为什么比 title 更可靠
盲人阅读器(如 NVDA、VoiceOver)优先读取 aria-label,而 title 在多数情况下被忽略或仅作悬浮提示——尤其在触屏设备或键盘导航中几乎不触发。很多开发者误以为加了 title="删除" 就够了,结果按钮朗读成“button”,完全没内容。
-
aria-label是显式声明,强制覆盖默认可访问性名称;title只是辅助信息,不参与无障碍树构建 - 对无文本的图标按钮(如
<button><i class="icon-trash"></button>),必须用aria-label="删除当前项目",不能依赖 CSS 伪元素或隐藏文字 - 避免同时写
aria-label和可见文本,否则会重复朗读;如有可见文字,改用aria-labelledby关联
role="button" 不等于真按钮
用 <div onclick="..." role="button"> 模拟按钮,阅读器能识别角色,但缺失原生语义和键盘行为——空格/回车键不触发,Tab 键无法聚焦(除非手动加 tabindex="0"),且不响应 :focus-visible 样式。
- 优先用
<button>或<a href="#">(后者需确保有 href 才能被聚焦) - 若必须用
div,至少补全:tabindex="0"+role="button"+onkeydown="if(event.key==='Enter'||event.key===' '){...}" - 阅读器朗读时,
role="button"会读作“button”,但不会自动读出操作后果(如“提交表单”),需靠aria-label补充动词+宾语
表格要带 scope 或 id/headers 关联
纯靠 CSS 隐藏的表头(如 display: none)会让阅读器彻底丢失行列关系,朗读变成一串无上下文的单元格值。常见错误是只写 <th>姓名</th><th>邮箱</th>,却不标注哪列属于哪行。
- 简单表格用
scope="col"(列头)或scope="row"(行头),例如:<th scope="col">邮箱</th> - 复杂嵌套表头必须用
id+headers显式关联:<th id="h1">订单状态</th>→<td headers="h1">已发货</td> - 避免用
aria-hidden="true"包裹表头——这会直接移除该元素的无障碍暴露,不是“隐藏视觉但保留语义”
动态内容更新要用 aria-live
AJAX 加载后插入新内容(如搜索结果、表单校验提示),阅读器默认不主动朗读,用户根本不知道发生了什么。单纯 focus 新元素也不可靠——屏幕阅读器焦点可能被重置或跳过。
立即学习“前端免费学习笔记(深入)”;
- 给实时更新容器加
aria-live="polite"(低优先级,不打断当前朗读)或aria-live="assertive"(高优先级,立即中断并朗读),例如:<div aria-live="polite" aria-atomic="true"></div> -
aria-atomic="true"确保整个区域内容变化时整体朗读,而非只读变更部分;false则可能只读新增文本,漏掉上下文 - 不要把
aria-live放在表单元素内部(如<input aria-live="polite">),它只作用于容器,且需独立 DOM 节点



















