必须用 aria-live 的场景是内容动态插入且无焦点移动时,如搜索建议、实时评论、表单提示;需按紧急程度选 polite/assertive/off,并避免语义冲突与残留属性。

交互反馈状态不是靠视觉样式“猜出来”的,而是要通过 ARIA 属性明确告诉辅助技术“现在发生了什么”。不配或配错 aria-live、aria-busy、aria-expanded 这类属性,会导致屏幕阅读器用户完全错过加载中、展开/收起、表单验证失败等关键反馈。
什么时候必须用 aria-live?
当内容是动态插入、且没有焦点移动时,读屏器默认不会播报——比如搜索建议列表、实时评论流、表单提交后的提示文案。此时不能只靠 CSS 显示/隐藏,得加 aria-live 声明播报策略。
-
aria-live="polite":适合非紧急反馈,如“已保存”,等当前播报自然结束后再读 -
aria-live="assertive":打断当前播报,用于错误或中断性提示,如“密码不符合要求” -
aria-live="off"(或移除该属性):禁用播报,别留着空值或aria-live="",Lighthouse 会报错 - 避免在
div上直接写aria-live后又塞进button或input——语义冲突会让读屏器跳过或重复播报
aria-expanded 和 aria-selected 别混用
这两个都描述状态,但适用场景完全不同:aria-expanded 只用于可展开/折叠的控件(如下拉菜单、手风琴标题),而 aria-selected 是给多选容器里的子项用的(如 role="tablist" 中的 role="tab",或 role="listbox" 中的 role="option")。
- 下拉按钮必须同步更新:
aria-expanded="true"时,对应菜单要display: block且aria-hidden="false";关闭时设为false并确保菜单aria-hidden="true" -
aria-selected="true"不能只写在 HTML 静态结构里——它必须随 JS 逻辑实时切换,否则读屏器永远读“已选中”,哪怕 UI 已取消 - 别在
button上同时写aria-expanded和aria-pressed:前者表示“关联内容是否展开”,后者表示“按钮自身是否被按下”,语义重叠且易出错
aria-busy 的真实使用边界
aria-busy="true" 不是“加载中”的万能替代,它只适用于整个区域处于不可交互状态(比如表格正在重新渲染数据、编辑器正在格式化),且该区域本身有明确角色(如 role="grid" 或 role="application")。
立即学习“前端免费学习笔记(深入)”;
- 普通按钮点击后显示 loading 图标?不需要
aria-busy,改用aria-disabled="true"+aria-label="提交中"更准确 - 表格加载新页数据时,可在
table外层包裹的div上设role="grid"+aria-busy="true",并确保子行暂时不可聚焦 -
aria-busy="true"必须配合视觉 loading 状态,且完成后必须显式设回false或移除——残留的aria-busy="true"会让读屏器持续忽略该区域所有变化
最常被忽略的点是:状态属性不是“写一次就完事”。它们必须和 DOM 更新、焦点管理、视觉反馈三者严格同步。一个 aria-expanded 没及时切回 false,可能让视障用户反复听到“菜单已展开”,而实际早已关闭。



















