div本身无语义,加role是强行覆盖而非增强,仅三类场景需用:js动态控件、无法重构的旧容器、无语义锚点的浮层;误用如role="button"套button或nav套role="navigation"会破坏可访问性;role需配套属性与状态同步,否则无效。

div 本身没有语义,加 role 不是“增强”,而是“强行覆盖”——它只在原生标签无法表达意图时才该用,用错比不用更危险。
哪些 div 必须加 role
只有三类场景值得动 role:
- JS 动态渲染的自定义控件(比如用
div实现的下拉菜单、滑块、树形组件) - 旧项目里无法重构的容器(如
<div class="main-content">),且该区域在无障碍树中缺失上下文 <li>弹窗、通知条等 JS 插入的浮层,DOM 中无明确语义锚点</li> <p>其他情况——比如只是布局容器、卡片外层、列表项包装——加 <code>role反而干扰可访问性树,浏览器可能丢弃节点或触发校验警告。role="button"和role="navigation"的典型误用常见错误是把语义已明确的结构再套一层
role:-
<button role="button"></button>:冗余,导致读屏器重复播报“按钮,按钮” -
<nav role="navigation"></nav>:覆盖原生nav的隐式行为(如快捷键跳转、焦点管理),旧版 VoiceOver 可能忽略 <div class="header" role="banner">:若页面已有 <code><header></header>,这属于语义冲突;若没header,应优先补header而非div + role原则很简单:能用
header、nav、main就别用div+role。role单独存在基本无效role是契约,不是贴纸。漏掉配套属性,屏幕阅读器只会读出角色名,其余行为全无保障:-
role="tab"必须嵌套在role="tablist"内,且需同步设aria-selected、tabindex和对应tabpanel的aria-hidden -
role="dialog"必须配aria-modal="true"、aria-labelledby(指向真实可见标题)、手动焦点陷阱 -
role="alert"必须搭配aria-live="assertive",且内容要直接插入 DOM,不能仅靠innerHTML更新
JS 更新视觉状态后,常忘了同步
aria-expanded或aria-checked——这是键盘用户卡住的最常见原因。真正难的不是写对
role,而是确保它和 DOM 状态、键盘交互、焦点流完全同步。一个没配齐的role="dialog",视障用户可能根本感知不到弹窗存在。-
-











