实时区域属性的滥用会导致次要信息频繁打断当前播报
别名: aria-live 滥用 · assertive 打断 · 实时区域
概念解释
aria-live、role="alert"、aria-atomic 是补充属性,用来把「这块变了」标成阅读器可订阅的区域。实时区域滥用(live region abuse)指的是把这组属性贴到不该订阅的容器上:整页、聊天记录、倒计时、每一次输入校验、广告槽。阅读器会把区域内的文本变化插进当前语音。次要更新因此一次次打断正在读的句子。问题出在属性贴错了地方、贴得太宽,不是「要不要通知动态更新」这条产品原则本身。
机制
实时区域一旦标上,阅读器就对该子树的文本突变建立监听。assertive / alert 会清掉当前语音队列再念;polite 理论上排队,但区域内任何一次字符变化都是一次候选。容器越大,无关突变越多:祖先被标成 live,子孙里的时钟、字数统计、滚动加载都会抢麦。aria-atomic="true" 还把整块再念一遍,一次小改写成一段长播报。
第二层是补充属性的「默认过强」。作者常把 alert 当成「让它响一下」的开关,贴在成功提示、打字反馈、购物车角标上。alert 带 assertive 语义,等于授权打断。属性没有「重要性」字段可调,只有这块区域在不在监听集合里。监听集合膨胀,播报队列就被次要信息占满。
怎么研究
在 NVDA 或 VoiceOver 里完成一项主任务(读一段说明、填表),同时让页面产生次要更新:角标 +1、未读数、autosave、「正在输入」。记录语音被打断的次数、被清掉的未念完句子、用户是否丢了主任务的位置。再做对照:把 live 从宽容器收到达标的那一个节点,或去掉 alert 改成普通状态。JAWS 与 NVDA 对 polite 排队的激进程度不同,要两边都记。
自变量:live 挂在哪一层、assertive vs polite vs alert、区域内无关突变频率。
因变量:打断次数、主任务完成、被取消的语音长度。
边界
真正的紧急(会话超时、支付失败、焦点仍在别处的错误)需要打断,这时 alert 不是滥用。日志型区域(role="log")本意就是持续追加,用在聊天记录上合理,用在每秒刷新的行情上就不合理。移动端阅读器对 live 的实现更碎,有的 polite 几乎不念,作者会为了「听见」改成 assertive,于是滥用从桌面转移到手机。用户把阅读器设成「提示更少」时,同一套属性会表现为「没反应」,不能再用加宽 live 去补。
怎么落地
- 只把
aria-live贴在专门承接通知的节点上,不要贴在body、主栏、整张表单。 - 禁止用
role="alert"表达非打断信息;角标、草稿已保存、字数统计不要进 assertive。 - 区域内不要放时钟、进度百分之一跳变、滚动加载出来的卡片。
- 验证:戴上耳机做完主任务,数被打断的次数。每一次打断记下是哪个节点、哪条属性。把 live 从祖先挪到叶子后再做一遍,打断应降到只剩真正要插队的那几条。