真正稳定可用的role值不足10个,应优先选用role="alert"、role="dialog"+aria-modal="true"、role="navigation"、role="status"及listbox/option/combobox组合;避免滥用role="application"等高风险值,原生语义足够时切勿覆盖role,且role不可动态修改。

哪些role值真能用、该优先选
日常开发里真正稳定、兼容好、读屏支持稳的role值不到10个,别被WAI-ARIA规范里60+个枚举值吓住。优先选这些:
-
role="alert":用于中断性提示(如表单校验失败),必须配aria-live="assertive" -
role="dialog"+aria-modal="true":模态框硬性组合,缺一不可 -
role="navigation":包裹主导航,比单纯<nav>多一层老JAWS兼容保障 -
role="status":适合非中断性更新(如“已保存”),但注意部分读屏只读首次内容 -
role="listbox"、role="option"、role="combobox":下拉类自定义控件必需组合,不能单用
像role="application"这种要慎用——它会让VoiceOver/NVDA切换到“应用模式”,Tab键失效、箭头键失灵,普通网页加了等于制造障碍。
role="dialog"为什么加了还是没反应
只写role="dialog",读屏器只会读“对话框”,其余什么都不会做:焦点不进、背景不锁、标题不读。必须同时满足三个硬性条件:
-
aria-modal="true"(不是可选,是WAI-ARIA 1.1强制要求) -
aria-labelledby指向一个真实存在、可见、未被aria-hidden="true"或display: none隐藏的标题元素ID - 手动实现焦点陷阱:打开后
focus()到第一个可交互子元素,Tab键循环限制在弹窗内,关闭后focus()回触发按钮
漏掉任意一项,视障用户就可能完全感知不到弹窗,或操作后焦点丢失在页面顶部。
立即学习“前端免费学习笔记(深入)”;
给
不是。反而危险。
<button>已有隐式role="button"和完整键盘支持(Enter/Space触发、自动tabindex、焦点反馈)。再加role="button"是冗余,可能干扰辅助技术解析;想让它跳转,该改JS逻辑,而不是骗读屏器说它是链接。
同理:<input type="checkbox">自带role="checkbox"和自动管理的aria-checked,手动设aria-checked="true"会导致JS状态与AT状态不同步。
原则很直白:原生语义够用,就别动role。强行覆盖,等于把浏览器和读屏器的信任契约撕了。
动态加role为什么屏幕阅读器没反应
因为role是静态契约,不是运行时指令。辅助技术只在元素插入DOM时读取一次role,后续JS修改(比如从role="button"改成role="alert")不会触发语义重计算。
正确做法是:
- 状态变化不用改
role,改用aria-live区域配合文本更新(比如提前写好<div aria-live="polite"></div>,再往里注入文本) - 真需切换角色(极少见),应销毁旧元素、重建新元素并重新聚焦
- 别在
display: none或visibility: hidden元素上设role——这些元素本就不在可访问树中,设了也无效
最常被忽略的是:role定义“这个元素**是什么**”,不是“它**现在正在做什么**”。视觉变了,DOM没同步更新aria状态,读屏看到的就是静止的旧语义。



















