角色 文档结构
tabpanel
标记与某个标签页配对的内容面板。每个 tabpanel 通过 aria-labelledby 由其对应的 tab 命名;tab 则通过 aria-controls 引用该面板。每次仅显示一个面板,其余面板使用 hidden 属性隐藏。
适用场景
用于承载某个标签页内容的容器。通过 aria-labelledby 将每个 tabpanel 与其对应的 tab 关联(指向 tab 的 id);tab 则通过 aria-controls 反向指向面板,形成互指关系。应使用 hidden 属性隐藏非激活面板——而非仅通过 CSS 设置 display: none——以确保无障碍树与视觉状态保持一致。
若面板包含交互内容(如表单、链接列表),可通过 tabindex="0" 使面板可聚焦。这样,激活标签页后,下一次按 Tab 键焦点将落入面板内部。
若面板内只有一个可聚焦区域——例如一个大标题后跟随内容——在面板上设置 tabindex="0" 即可。若面板内包含大量可聚焦控件,用户可直接 Tab 至这些控件,tabindex 则为可选项。
常见错误
- 通过 CSS 隐藏 tabpanel,但未设置
hidden属性。屏幕阅读器仍可能暴露其内容。 - tabpanel 缺少
aria-labelledby——将被播报为”标签面板”,没有名称。 - tab 通过
aria-controls指向 tabpanel 的 id,但面板未通过aria-labelledby反向指回 tab。两者的关联必须互相对应。 - 所有 tabpanel 保留在 DOM 中,仅通过动态切换
display: none来隐藏,但未设置hidden属性。审计人员会将此标记为不一致。 - 将
role="tabpanel"应用于未与role="tab"配对的面板——形成孤立的 tabpanel。
示例
<div role="tablist" aria-label="Settings">
<button role="tab" id="t-account" aria-selected="true" aria-controls="p-account" tabindex="0">Account</button>
<button role="tab" id="t-billing" aria-selected="false" aria-controls="p-billing" tabindex="-1">Billing</button>
</div>
<section role="tabpanel" id="p-account" aria-labelledby="t-account" tabindex="0">
<h2>Account</h2>
<p>…</p>
</section>
<section role="tabpanel" id="p-billing" aria-labelledby="t-billing" tabindex="0" hidden>
<h2>Billing</h2>
<p>…</p>
</section>