role属性是显式覆盖元素默认语义的开关,仅在无障碍树中生效;必须用于动态渲染、旧浏览器兜底、非标准容器及按钮化非按钮元素等场景,禁用与原生语义冲突的混用。

role 属性不是语义“补丁”,而是语义覆盖开关——只在原生标签无法准确表达组件意图时才该用;加错、漏配、不联动状态,比不加更危险。
哪些元素必须加 role,哪些绝对不能加
必须加 role 的典型场景只有三类: 绝对不能加 role 的是已有明确原生语义的元素: 只写 漏掉任意一项,视障用户可能完全感知不到弹窗,或操作后焦点丢失在页面顶部。 每个 role 都绑定一套最小语义契约,缺配套属性就等于无效声明: 最常被跳过的是:JS 更新了视觉状态(比如切换了 tab 样式),却忘了同步设置 别只看代码写了没,要进真实环境检查: 动态修改 div 或 span 实现的自定义控件(如下拉菜单、滑块)、旧项目中无法重构但需补语义的容器(如 button、nav、main、h1、input 等。例如:
:冗余,可能干扰焦点管理或导致读屏重复播报:覆盖后让屏幕阅读器误判为页头,破坏 landmark 结构:语义与行为脱节,空格键无法切换,AT 会报“不可操作”role="dialog" 必须配齐的三个硬性条件
role="dialog" 几乎等于没写——屏幕阅读器只会读出“对话框”,其余行为全无保障。
aria-modal="true"(WAI-ARIA 1.1 强制要求;IE 不支持,需降级 fallback)aria-labelledby,且值指向一个真实存在、可见、未被 aria-hidden="true" 或 display: none 隐藏的标题元素 IDfocus() 到第一个可交互子元素;Tab 键循环限制在弹窗内;关闭后 focus() 回触发按钮role 单独存在基本没意义
role="slider" 必须同步有 aria-valuenow、aria-valuemin、aria-valuemax,并响应方向键role="tab" 必须嵌套在 role="tablist" 内,配合 aria-selected 和 tabindex,且对应 tabpanel 要靠 aria-hidden 控制显隐role="alert" 必须搭配 aria-live="assertive",且内容应直接插入而非仅靠 JS 改 innerHTML(部分读屏器只读首次注入)aria-selected 或 aria-expanded。辅助技术看到的是静止的 DOM,不是你的 CSS 类名。验证 role 是否真正生效的关键动作
Role 字段显示为你设置的值(不是 generic 或默认 fallback)role="navigation" 出现在列表中div,协作和维护成本反而升高role(比如从 button 改成 alert)不会触发语义重计算——大多数辅助技术只在元素插入 DOM 时读取一次 role。真需要切换角色(极少见),应销毁旧元素、重建新元素并重新聚焦。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











