通知栏必须用 role="alert" 或 aria-live="assertive",确保屏幕阅读器立即播报;dom位置需在header下方、main上方且为body直接子元素;内容须文字、图标、颜色三者兼具并满足无障碍标准。

通知栏必须用 role="alert" 或 aria-live="assertive"
屏幕阅读器不会自动播报普通 div 里的新文本,哪怕它突然出现在页面顶部。不加 ARIA 声明,用户根本不知道有新通知——尤其是盲人或低视力用户正在专注操作表单时。
正确做法是:把通知容器设为 role="alert"(适用于紧急、需立即处理的消息),或用 aria-live="assertive"(更灵活,支持动态替换内容)。两者都强制读屏器中断当前播报、立刻朗读新内容。
-
role="alert"只能用于独立、语义明确的提示区域,不能嵌套在form或dialog内部,否则会干扰主流程 -
aria-live="polite"适合非打断型提示(如“已保存”),但通知栏通常需要强提醒,别误用 - 若通知支持关闭按钮,
button必须带aria-label="关闭此通知",不能只写“×” - JS 动态插入通知时,确保 DOM 节点已挂载再设置
aria-live,否则部分读屏器(如旧版 NVDA)会忽略
DOM 插入位置直接影响键盘焦点与阅读顺序
把通知栏塞在 <footer></footer> 底部或 <main></main> 末尾,键盘用户 Tab 到底才看到它,视觉用户却第一眼就注意到了——这是典型的顺序断裂。
必须让通知容器在 DOM 中位于 <header></header> 下方、<main></main> 上方,且是 的直接子元素之一(和 <header></header>、<main></main> 并列)。这样既保证屏幕阅读器按视觉流优先读到,又能让 document.getElementById("notify").focus() 真正生效。
- 避免用
position: fixed+top: 0把通知“视觉上提上来”,但 DOM 还在底部——焦点流和读屏顺序完全脱节 - 响应式折叠时,如果通知被 JS 移动到 body 末尾,必须同步调用
aria-hidden="true"隐藏原位置,并给新节点补全role和tabindex="-1" - 同一时间只应存在一个活跃通知;替换旧通知时,先移除旧节点再插入新节点,避免读屏器连续播报两条
颜色、图标、文字三者缺一不可,但不能依赖任一单一通道
仅靠红色背景+感叹号图标表示错误,对色觉障碍或低视力用户无效;纯文字不配图标,认知障碍用户可能忽略关键信号。
必须同时满足:文字明确说明状态(如“上传失败:文件过大”)、图标使用 <svg></svg> 并带 aria-hidden="true"(避免重复播报)、背景色满足 WCAG AA 级对比度(至少 4.5:1),且错误类通知额外加 aria-atomic="true" 确保整条消息被完整朗读,不被截断。
- 禁止用
color: red单独传递语义;必须搭配文字前缀(如“错误:”)或图标 -
<img src="warn.png" alt="警告:操作未完成">中的alt文本要包含动作结果,不能只写“警告图标” - 动画闪烁(如
animation: pulse 2s infinite)必须提供关闭开关,否则可能诱发光敏性癫痫 - 通知消失逻辑不能只靠定时器;必须提供手动关闭按钮,并在关闭后触发
aria-hidden="true"+remove()
动态更新时的可访问性陷阱最容易被忽略
很多团队以为加了 aria-live 就万事大吉,结果用户听到的是“已发送”“已发送”“已发送”,因为 JS 每次都往同一个 div 的 textContent 里塞新字符串,读屏器识别为“内容变更”而非“新消息”,只读最后一条。
真正健壮的做法是:每次通知触发,创建全新 DOM 节点插入,旧节点立即 remove();或者用 aria-relevant="additions text" 显式声明关注新增文本,再配合 aria-atomic="false" 让读屏器只读变化部分。
- 不要复用通知容器的
innerHTML——这是最常见也最隐蔽的失效点 - 服务端推送通知(如 SSE)必须在客户端做节流,避免 1 秒内连发 5 条导致读屏器卡死或跳过
- 移动端双指滑动浏览时,通知若没设
tabindex="-1",可能意外抢走焦点,导致用户无法继续滚动
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











