必须手动同步 aria-selected 状态并确保 role="tab" 正确使用,否则读屏器无法感知选中变化;tab 元素需为 ,与 成对出现;切换时须清空旧项、设置新项、聚焦目标按钮;aria-selected 须与 hidden/aria-hidden 联动控制面板显隐;初始化设属性安全,但交互中需配合焦点移动或 aria-live 实现语音反馈。

必须手动同步,浏览器不会自动把视觉状态映射到 aria-selected;只改 CSS 类或 display 样式,读屏器完全感知不到选中变化。
tab 元素上必须显式写 role="tab"
很多“设了 aria-selected 没反应”的问题,根源是按钮没加 role="tab"。ARIA 规范明确限定:只有 role="tab" 元素才允许使用 aria-selected。用 <div> 或 <code><a></a> 模拟 tab 时,即使加了属性,屏幕阅读器也会直接忽略。
实操建议:
- 每个 tab 必须是
<button role="tab"></button>,不能是<span></span>或无语义容器 -
role="tab"必须和外层<div role="tablist"> 成对出现,缺一不可 <li>避免在 <code><ul><li></ul>结构里给<li>加role="tab"——语义错位,焦点管理会失效 - 每次点击前,先遍历所有
[role="tab"],统一设aria-selected="false" - 再给目标元素设
aria-selected="true" - 紧接着调用
targetButton.focus(),让焦点落到该 tab 上(不是靠 CSS:focus) - 别用
preventDefault()阻断默认行为——它可能中断焦点移动链,导致读屏器卡在上一个位置 - 激活的 tab 对应的
<div role="tabpanel"> 必须有 <code>hidden属性移除 +aria-hidden="false"+tabindex="0" - 非激活面板必须带
hidden(比display: none更可靠),且aria-hidden="true" - 不要只靠 CSS 切换
.active类来控制显隐——读屏器不识别这类类名
切换时要清空旧项、设置新项、再聚焦
仅调用 element.setAttribute("aria-selected", "true") 不够,还必须确保上一个 tab 的 aria-selected 被设为 "false",且新 tab 真正获得键盘焦点。否则读屏器可能同时读出两个“已选中”,或根本无法定位当前项。
实操建议:
aria-selected 和 hidden/aria-hidden 必须联动
aria-selected="true" 只表示“这个 tab 被选中”,不代表对应内容区就该显示。面板是否可见,由 hidden 属性或 aria-hidden 控制,这两者必须和 aria-selected 同步更新,否则读屏器会读到隐藏内容,或跳过本该播报的面板。
实操建议:
最易被忽略的一点:初始化时设好 aria-selected="true" 是安全的,但交互中仅改属性不会触发读屏播报;若需即时语音反馈,得配合 aria-live 区域写入文本,或者依赖焦点移动本身触发播报。











