details标签原生支持手风琴效果,点击一个自动收起其他已展开项;同时展开是因人为破坏默认行为,如静态设open属性、JS强制设置或CSS覆盖;需确保互斥可用toggle事件监听控制。

details标签默认就是手风琴效果,不需要额外JS
HTML <details> 本身是原生折叠组件,浏览器自动实现单开单关——点一个<details>,其他已展开的会自动收起。这不是“独占”而是规范行为,源于details元素的语义和UA样式(User Agent stylesheet)控制逻辑。
常见误解是以为要靠JS模拟手风琴,其实只要不手动干预open属性或用JS强制多开,它天然就是互斥的。
多个details共存时,为什么有时会同时展开?
这是人为破坏了默认行为,典型原因有:
- 给多个
<details>都加了open属性(静态HTML里写死) - 用JS批量设置
element.open = true,没做状态清理 - CSS里写了
details[open] { display: block !important; }之类覆盖了原生折叠逻辑 - 在Vue/React中用
v-model或useState绑定多个open状态,但没同步控制互斥
想确保严格手风琴,推荐用<details> + 少量JS控制
纯HTML够用,但若需更可控(比如点击标题区域外也触发、支持键盘操作),可加轻量JS:
立即学习“前端免费学习笔记(深入)”;
document.querySelectorAll('details').forEach(detail => {
detail.addEventListener('toggle', () => {
if (detail.open) {
document.querySelectorAll('details:not([open])').forEach(d => d.removeAttribute('open'));
}
});
});
注意:toggle事件在Chrome/Firefox/Edge中稳定支持,Safari 15.4+ 也已支持;不要用click监听<summary>,因为用户可能用空格/回车触发,toggle才是语义正确时机。
移动端点击无响应?检查<summary>是否被遮挡或禁用
<details>的交互区域仅限<summary>内容部分,常见坑:
-
<summary>内嵌<button>或<a href="#">且没阻止默认行为,导致toggle不触发 - CSS写了
pointer-events: none或user-select: none到<summary>上 - 父容器有
overflow: hidden且<summary>超出裁剪,点击无效 - 使用了
position: absolute让<summary>脱离文档流,导致点击热区错位
最简验证方式:临时加style="outline: 1px solid red"到<summary>,看点击区域是否符合预期。
details的折叠动画不可直接CSS过渡(height不生效),如需动效得用max-height hack或CSS @starting-style,但这会绕过原生语义——权衡是否真需要视觉动效。



















