tab组件需严格匹配data-tab值与面板id、正确设置aria属性(role/aria-controls/aria-labelledby)、手动管理焦点流,并用role="tablist"包裹按钮,三者缺一不可。

data-tab 属性必须严格匹配 ID 或 class,不能靠 DOM 顺序推断
很多新手写完 button[data-tab="profile"] 和 div#profile-panel 就以为能自动关联,结果切换没反应——根本原因是 selector 不对。data-tab 的值只是个字符串,JS 里得用它拼出合法选择器,比如 document.querySelector(dataTabValue) 或 document.querySelector('[id="' + dataTabValue + '"]')。
常见错误包括:
- 按钮写
data-tab="user",面板却用id="user-info",没做映射就直接查querySelector("#" + value) - 面板用 class 而非 id,但 JS 里仍按
#xxx查,返回 null - 值里带空格或特殊字符(如
data-tab="tab 1"),没做encodeURIComponent或转义,CSS 选择器报错
推荐统一约定:所有 data-tab 值只含字母、数字、短横线,对应面板用 id,且保持完全一致。这样 document.getElementById(tabValue) 最快也最稳。
role="tab" 和 role="tabpanel" 必须成对出现,且 aria-controls/aria-labelledby 不可省略
仅靠显隐控制不是完整 Tab 组件。屏幕阅读器需要明确知道「这个按钮控制哪个面板」「这个面板由哪个按钮触发」。漏掉 aria-controls,键盘用户 tab 进来后根本不知道按了会显示什么。
正确写法示例:
<button role="tab" aria-controls="panel-security" aria-selected="true">安全</button> <div role="tabpanel" id="panel-security" aria-labelledby="security-tab">...</div>
注意要点:
-
aria-controls的值必须是目标面板的id,大小写、连字符全部要对上 -
aria-labelledby指向的是触发它的按钮的id(不是data-tab),所以按钮最好也加id="security-tab" - 首次加载时,激活态按钮必须设
aria-selected="true",对应面板不能只靠display: block,还得加hidden="false"或移除hidden属性
切换时必须手动管理焦点,否则键盘用户会“掉进空白”
点击切换后,焦点还停在按钮上,面板内容虽然显示了,但键盘用户按 Tab 键直接跳到下一个页面元素,而不是进入当前面板内部——这是无障碍最大硬伤。
修复逻辑很简单,在 JS 切换完面板显隐后加一行:
activePanel.focus();
但前提是面板有 tabindex="0":
- 如果面板内有可聚焦子元素(如
input、button),更推荐activePanel.querySelector('input, button, [href], [tabindex]:not([tabindex="-1"])').focus() - 别依赖 CSS 的
outline: none去隐藏焦点框,那只是视觉隐藏,对键盘导航毫无帮助 - 如果面板是纯展示内容(无交互元素),至少给
div[role="tabpanel"]加tabindex="0",确保能被聚焦
Tab 容器必须用 role="tablist" 包裹,且不能嵌套其他交互元素
把几个 button[role="tab"] 直接扔在 div 里,不加 role="tablist",屏幕阅读器会把它们读作“五个独立按钮”,而不是“一个标签页组里的五个选项”。这破坏了语义结构,也让键盘导航无法按 Tablist 规范工作(比如 ArrowLeft/ArrowRight 循环)。
同时要注意容器内不能混入其他可交互元素:
- 别在
role="tablist"里放a标签(除非href="#"且preventDefault)、input或下拉菜单 - 如果需要操作按钮(如关闭 tab、新增 tab),应放在
tablist外部,或用aria-hidden="true"隔离其语义 - 移动端小屏下若折叠为下拉菜单,
role="tablist"必须动态替换为role="combobox",否则语义错乱
真正难的不是让 Tab 显示出来,而是让每一种访问方式——鼠标、触屏、键盘、读屏软件——都拿到一致的状态和路径。DOM 结构、ARIA 属性、焦点流,三者缺一不可。漏掉任意一个,都可能让某个用户群体完全无法使用这个组件。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











