动态内容需加 aria-live 才能被屏幕阅读器朗读;innerHTML 替换会销毁监听上下文,应逐个插入节点或重设 aria-live 属性;polite 适合常规更新,assertive 仅限严重错误;需配合焦点管理与显隐处理。

动态内容不加 aria-live,屏幕阅读器基本不会朗读——这不是兼容性问题,是根本没通知到。
为什么 innerHTML 替换后读屏完全无感
直接写 el.innerHTML = newContent 会销毁旧 DOM 节点并重建整个子树,aria-live 的监听上下文随之丢失。读屏器只响应“向已有容器内插入新节点”,不是“文本变了就播报”。
- 错误做法:
document.getElementById("list").innerHTML = "<li>新项</li>"→ 读屏静默 - 正确做法:先清空
el.textContent = "",再逐个el.appendChild(item)或用el.insertAdjacentElement("beforeend", item) - 若必须整块替换,得在新 HTML 字符串里重写
aria-live="polite"属性,否则后续更新失效 - 别把
aria-live加在带 CSS 过渡(如opacity、transform)的元素上,过渡期间 DOM 变化可能被跳过
aria-live="polite" 和 "assertive" 怎么选
两者行为差异极大,错用会导致打断用户或信息被忽略。
-
aria-live="polite":等用户暂停朗读后再播报,适合搜索结果、列表刷新、成功提示 -
aria-live="assertive":立即中断当前朗读,强制播报,仅限严重错误(如表单提交失败、权限拒绝) - 不要对轮播图、通知气泡滥用
assertive——频繁打断会让用户烦躁甚至放弃使用 - 若内容需完整朗读(比如一段含链接的提示),加
aria-atomic="true",否则读屏可能只读变化部分
动态加载后焦点没落到预期位置
htmx 或手写 JS 替换内容后,焦点常卡在原处或跑到页面顶部,键盘用户无法继续操作。
立即学习“前端免费学习笔记(深入)”;
- 优先让新内容中第一个可聚焦元素带
autofocus属性(如<input autofocus>),现代浏览器和读屏器普遍支持 - 若不能改 HTML,JS 中替换完手动调用
newFocusable.focus(),注意要等 DOM 渲染完成(可用requestAnimationFrame包一层) - 避免聚焦到
div或纯文本节点——必须是原生可聚焦元素(button、a[href]、input等)或明确设了tabindex="0"的元素 - 模态框打开后,焦点必须锁在内部;关闭时,焦点应回退到触发按钮——这点漏掉,键盘用户就出不来了
最易被忽略的是:动态区域一旦被 display: none 或 hidden 切换可见性,aria-live 就失效。它只监听“内容变更”,不监听“显隐切换”。需要显隐控制时,得配合重新挂载或手动触发 aria-live 容器的 textContent 更新。



















