标签无法原生支持多标签页互斥,需用javascript监听toggle事件并手动关闭其他同组项,同时补全aria角色、键盘导航等可访问性功能。

details 标签本身不支持多标签页切换
<details></details> 是语义化折叠控件,只管理单个展开/收起状态,没有原生的“标签页组互斥”逻辑。想用它模拟多标签页,必须配合 JavaScript 手动控制 open 属性,并阻止多个 <details></details> 同时打开。
手动实现标签页互斥的关键操作
核心是监听每个 <details></details> 的 toggle 事件,在一个打开时关闭其他所有同组的 <details></details>:
- 给所有同组
<details></details>添加相同 class(如tab-group)或 data 属性(如data-tab-group="main")便于批量选取 - 用
event.target.open === true判断当前是否被打开(注意:toggle触发时,open已更新) - 遍历同组其他元素,对非当前项调用
el.removeAttribute('open')(不能设open = false,因为布尔属性存在即为真) - 避免在
toggle中直接修改event.target的open,否则可能触发二次 toggle
document.querySelectorAll('.tab-group').forEach(tab =>
tab.addEventListener('toggle', function(e) {
if (e.target.open) {
document.querySelectorAll('.tab-group').forEach(other =>
if (other !== e.target) other.removeAttribute('open')
);
}
})
);
为什么不用 summary 的 click 事件?
<summary></summary> 的 click 事件无法可靠捕获用户点击行为:iOS Safari 和部分安卓浏览器中,点击 summary 区域可能不触发 click;而 toggle 是标准事件,只要 <details></details> 状态变化就触发,兼容性更稳。
-
click在 summary 内嵌按钮、链接或 SVG 时容易失效或冒泡混乱 -
toggle是唯一能准确反映“用户意图展开/收起”的事件 - 不要监听
change——<details></details>不触发该事件
样式和可访问性必须手动补足
原生 <details></details> 没有 active/tabindex/role 等标签页必需语义,屏幕阅读器不会将其识别为 tabs 组件:
- 需为每个
<summary></summary>添加role="tab",父容器加role="tablist" - 展开项的
<div> 内容区加 <code>role="tabpanel",并用aria-labelledby关联对应 summary 的 id - 用 CSS 控制
[open] > summary::after替换默认三角箭头,保持视觉一致性 - 键盘操作(Tab / → / ←)需 JS 实现,
<details></details>默认不支持方向键切换
真正需要生产级标签页,建议用 <div role="tablist"> + ARIA 实现,或使用成熟组件库(如 Shoelace 的 <code><sl-tab-group></sl-tab-group>)。硬套 <details></details> 只适合极简场景,且必须接受其语义和交互局限。











