HTML如何做选项卡无障碍_html tab选项卡aria角色设置【附代码】并不只看表面做法,关键还要理解相关条件、限制和后续影响。
选项卡组件必须使用语义化 ARIA 属性:role="tablist" 包裹 role="tab",每个 tab 关联 role="tabpanel",并正确设置 aria-controls、aria-labelledby、tabindex、aria-selected 和 aria-hidden,否则屏幕阅读器无法识别和导航。
仅用 div + class 控制显隐,屏幕阅读器完全感知不到这是个选项卡组件。必须显式声明语义角色:role="tablist" 包裹一组 role="tab",每个 tab 对应一个 role="tabpanel"。否则 NVDA、VoiceOver 会把它读成普通段落或列表,用户无法用键盘 →/← 切换标签页。
常见错误写法:
<div class="tabs"><div class="tab active">首页</div></div>
这没有任何可访问性保障。正确结构必须包含 aria-controls 和 aria-labelledby 关联关系。
默认 div 不在 Tab 键顺序中。每个 role="tab" 至少要设 tabindex="0"(初始可聚焦),激活后要把其他 tab 设为 tabindex="-1",同时把焦点移到对应 tabpanel 的第一个可聚焦子元素(比如 h2 或 button)。
关键点:
autofocus —— 它在 tab 切换时不可靠Enter 或 Space 触发切换,不是仅靠 click
keydown 监听 ArrowLeft/ArrowRight 实现键盘导航aria-selected="true",其他为 "false"
别用 display: none 或 visibility: hidden 隐藏非活动面板 —— 这会让屏幕阅读器直接跳过内容,即使它本该被读出(比如用户刚切过去还没来得及听)。正确做法是保留 DOM 结构,用 aria-hidden="true" 配合视觉隐藏(如 clip-path 或 position: absolute; clip: rect(1px, 1px, 1px, 1px))。
示例关键属性组合:
<div role="tabpanel" aria-labelledby="tab-home" aria-hidden="true"> <h2 id="panel-home-title">首页内容</h2> <p>这里是首页正文…</p></div>
切换时同步更新 aria-hidden 和 aria-selected,否则语音反馈会错乱。
Chrome(含 Edge)原生支持 Tab → ArrowRight 切换,但 Safari + VoiceOver 默认不触发,必须靠 JS 拦截 keydown 并调用 focus()。更麻烦的是,Safari 会把 role="tab" 当作按钮处理,导致 Enter 和 Space 都触发 —— 你得防重复执行。
稳妥做法:
keydown,对 ArrowLeft/ArrowRight 阻止默认行为并手动移动焦点Enter 和 Space 只执行一次切换(加 flag 或用 event.preventDefault())aria-controls、aria-labelledby、tabindex、aria-selected、aria-hidden 这五个属性一个都不能少,缺任何一个,对依赖语音导航的用户来说,这个选项卡就等于不存在。