aria-selected 必须配合 role="tab" 等语义角色才生效,需在 tab 元素上手动设置并同步 aria-hidden,同时确保 tabindex、aria-labelledby 和键盘导航支持。

aria-selected 必须配合 role="tab" 才生效
直接给 <div> 或 <code><span></span> 加 aria-selected="true" 不会被屏幕阅读器识别。它只在语义明确的上下文中起作用,比如 role="tab"、role="option"、role="row" 等。选项卡场景下,必须确保每个可点击的 tab 元素是 <button role="tab"></button>(不能用 <a></a> 或 <div> 代替),且外层包裹 <code><div role="tablist">。
<p>常见错误:</p>
<ul>
<li>用 <code><li><a></a></li> 模拟 tab —— 链接默认会跳转,且不支持 aria-selected 的语义绑定
role="tablist" 容器 —— 屏幕阅读器无法建立“一组可切换项”的上下文aria-selected 写在 <div role="tablist"> 上 —— 它只对子级 <code>role="tab" 元素有效
切换时必须手动同步 aria-selected 和 aria-hidden
仅靠 CSS 类(如 .active)切换视觉状态,aria-selected 不会自动更新,读屏完全感知不到变化。JavaScript 必须显式操作属性:
- 先遍历所有
role="tab"元素,统一设aria-selected="false" - 再给当前激活的 tab 设
aria-selected="true" - 同时,对应
role="tabpanel"设aria-hidden="false",其余设aria-hidden="true" - 非激活 panel 还应加
hidden属性(比display: none更可靠)
示例关键片段:
const tabs = document.querySelectorAll('[role="tab"]');<br>tabs.forEach(tab => tab.setAttribute('aria-selected', 'false'));<br>targetTab.setAttribute('aria-selected', 'true');<br>document.getElementById(targetTab.getAttribute('aria-controls')).setAttribute('aria-hidden', 'false');
键盘导航失效?大概率没处理 ArrowRight/ArrowLeft
ARIA 规范要求 tablist 支持方向键切换,但浏览器不会自动实现。仅靠 click 事件监听远远不够:
- 必须监听
keydown事件,在tablist容器上捕获ArrowRight/ArrowLeft - 按需移动焦点:调用
nextTab.focus(),不能只改aria-selected - Home/End 键要分别聚焦第一个/最后一个 tab
- Safari + VoiceOver 下,
Enter和Space都会触发按钮,需防重复执行(例如用event.preventDefault()后再调用逻辑)
为什么用了 aria-selected 还是没播报“已选中”?
最常被忽略的三点:
-
role="tab"元素没设tabindex="0"(激活态)或tabindex="-1"(非激活态)—— 焦点无法落到元素上,读屏就无法关联状态 - 对应
tabpanel缺少aria-labelledby指向 tab 的 id —— 读屏可能读不出面板标题 - 没用 DevTools 的 Accessibility 面板实时验证:右键检查元素 → Elements 标签页 → 右侧 Accessibility → 查看 “Selected” 是否为 true、Role 是否正确
复杂点在于:同一时间只能有一个 aria-selected="true";多选不是靠多个 aria-selected,而是靠父容器的 aria-multiselectable="true" —— 但选项卡是单选场景,这个值必须是 false 或省略。











