R3.09.3live region announcement设计

动态变化需要主动播报而非只改样式

别名: aria-live · live region · role=status · 动态播报 · polite assertive

概念解释

画面上刚发生的变化——错误变红、角标从 0 到 3、吐司滑入、加载结束——对视力用户是一次视觉瞬变。辅助技术默认不监视像素,不会因为颜色或图标换了就开口。未聚焦处的动态变化必须被主动播报(announcement),通常经由 aria-live 区域、role="status" / role="alert",或改写会被重新计算的名称与状态。只改样式等于只通知了看着屏幕的人。

它处理的是「焦点不在这块上时,变化如何被听见」,不是名称、角色、状态这三个槽本身怎么填,也不是把节点从树上拿掉。

机制

屏幕阅读器跟踪焦点和用户显式导航。焦点外的 DOM 突变,只有被标成 live region 的子树,或导致当前控件名称/状态重算的属性变化,才会进入播报队列。CSS 颜色、background-image、纯装饰的伪元素、仅视觉上的勾选图标,都不会触发这条队列。aria-live="polite" 等当前语句读完再报,"assertive" 会打断;role="status" 默认 polite,role="alert" 默认 assertive。区域必须在变化之前就存在于树上:先插入空的 live 容器,再写入文本,引擎才能观察到「这块活区变了」。先插入整段带 live 的新节点,有的引擎会当成一次普通出现而不报。

播报还受忙碌与冗余约束。短时间连续改同一个 live 节点,可能只报最后一次;把整页标成 live 会把滚动和无关更新打成噪音,用户会关掉读屏的 live 功能。因此通道要窄:一条状态、一次错误、一次完成,而不是整块界面的每一次重绘。

边界

用户正在操作的那个控件,状态变化往往已经随焦点朗读(开关被按、菜单被展开),不必再抄一份到 live region,否则会报两遍。长时间过程用进度值或 aria-busy 表达「还在进行」,不要每百分之一都 assertive 打断。聊天、行情、日志这类高频流,live 只能摘要或按用户手势拉取,不能逐条 assertive。关闭读屏、只用放大镜的低视力用户看不见也听不到 live,视觉上的变化仍要自己站得住。部分移动引擎对 aria-live 的支持不完整,关键错误不能只活在这一条通道里。

怎么落地

  • 把表单错误、保存成功、购物车数量、后台完成这类「焦点外必须知道」的消息写入事先存在的 live 区域,而不是只把字段描红或换图标。
  • 默认 polite;真正要打断的(会话到期、支付失败)才用 assertive / alert。同一时刻只让一个 live 区域说话。
  • 先挂空容器再改文本;不要把 live 属性跟整段新 DOM 一起插入。避免把布局根节点设成 live。
  • 验证:焦点停在别处,触发那次变化,听屏幕阅读器是否报出那一句、是否报两遍、是否被后续无关更新冲掉。再关掉读屏,确认视觉通道自己仍然成立。

延伸

  • 同组R3.09.1 名称、角色、状态缺一辅助技术就无法表达 · R3.09.2 视觉隐藏与语义隐藏是两件事
  • 相邻R3.01 语义结构 · R3.02 焦点管理
  • 站内检索aria-live · live region · role=status · announcement

同组卡片

快捷操作

分享

分享当前页面

ios_share

https://hci.top/zh/handbook/R3.09.3