HTML如何做选项卡无障碍_html tab选项卡aria角色设置【附代码】

作者:袖梨 2026-08-05

HTML如何做选项卡无障碍_html tab选项卡aria角色设置【附代码】并不只看表面做法,关键还要理解相关条件、限制和后续影响。

选项卡组件必须使用语义化 ARIA 属性:role="tablist" 包裹 role="tab",每个 tab 关联 role="tabpanel",并正确设置 aria-controls、aria-labelledby、tabindex、aria-selected 和 aria-hidden,否则屏幕阅读器无法识别和导航。

tablist 里必须用 role="tab",不能只靠 CSS 样式切换

仅用 div + class 控制显隐,屏幕阅读器完全感知不到这是个选项卡组件。必须显式声明语义角色:role="tablist" 包裹一组 role="tab",每个 tab 对应一个 role="tabpanel"。否则 NVDA、VoiceOver 会把它读成普通段落或列表,用户无法用键盘 / 切换标签页。

常见错误写法:

<div class="tabs"><div class="tab active">首页</div></div>

这没有任何可访问性保障。正确结构必须包含 aria-controlsaria-labelledby 关联关系。

tab 必须有 tabindex="0" 或 tabindex="-1",且需手动管理焦点

默认 div 不在 Tab 键顺序中。每个 role="tab" 至少要设 tabindex="0"(初始可聚焦),激活后要把其他 tab 设为 tabindex="-1",同时把焦点移到对应 tabpanel 的第一个可聚焦子元素(比如 h2button)。

关键点:

  1. 不要依赖 autofocus —— 它在 tab 切换时不可靠
  2. EnterSpace 触发切换,不是仅靠 click
  3. keydown 监听 ArrowLeft/ArrowRight 实现键盘导航
  4. 当前激活的 tab 必须设 aria-selected="true",其他为 "false"

tabpanel 必须用 aria-hidden="true/false" 控制隐藏逻辑

别用 display: nonevisibility: hidden 隐藏非活动面板 —— 这会让屏幕阅读器直接跳过内容,即使它本该被读出(比如用户刚切过去还没来得及听)。正确做法是保留 DOM 结构,用 aria-hidden="true" 配合视觉隐藏(如 clip-pathposition: 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-hiddenaria-selected,否则语音反馈会错乱。

Chrome 和 Safari 对 role="tab" 的键盘行为支持不一致

Chrome(含 Edge)原生支持 TabArrowRight 切换,但 Safari + VoiceOver 默认不触发,必须靠 JS 拦截 keydown 并调用 focus()。更麻烦的是,Safari 会把 role="tab" 当作按钮处理,导致 EnterSpace 都触发 —— 你得防重复执行。

稳妥做法:

  1. 监听所有 keydown,对 ArrowLeft/ArrowRight 阻止默认行为并手动移动焦点
  2. EnterSpace 只执行一次切换(加 flag 或用 event.preventDefault()
  3. 测试时务必打开 VoiceOver(macOS)和 NVDA(Windows),别只信 Chrome DevTools 的无障碍树
实际可用的最小闭环结构里,aria-controlsaria-labelledbytabindexaria-selectedaria-hidden 这五个属性一个都不能少,缺任何一个,对依赖语音导航的用户来说,这个选项卡就等于不存在。

相关文章

精彩推荐