details标签原生支持多选展开,多个并列的details默认各自独立、互不影响;name属性在现代浏览器中强制互斥,会禁用多选能力,故多选时应避免同名或不设name。

details标签原生不支持多选展开
直接用多个<details></details>并列写,它们默认就是各自独立、互不影响的——点开一个,其他不会自动收起,这恰恰就是“多选展开”的行为。不需要额外配置,也不该强行加逻辑去破坏它。很多人误以为这是 bug 或需要修复,其实浏览器完全按规范执行:每个<details></details>维护自己的open状态。
为什么不能用name属性实现多选?
name属性在现代浏览器(Chrome 117+/Firefox 119+/Safari 17.4+)中用于**强制互斥**,即同名<details></details>只能有一个open。它和“多选”目标相反。如果你写了name="faq",反而会禁用多选能力。要多选,就别设name,或确保每个<details></details>的name值都不同(甚至不写)。
动态内容加载时防重复插入
点击展开才加载详情内容(比如 fetch 后innerHTML),最容易在反复开关中重复请求、重复渲染。关键不是阻止开关,而是控制插入逻辑:
- 用
data-loaded="true"标记已加载项,每次toggle事件里先检查该属性 - 只在
event.target.open === true && !el.hasAttribute('data-loaded')时发起请求并插入 - 插入后立刻
el.setAttribute('data-loaded', 'true'),避免下次再触发 - 不要在
toggle回调里直接操作el.open,否则可能引发 Safari 的微任务竞态
嵌套details也能多选,但要注意结构
子<details></details>是否展开,完全独立于父级——这是合法且稳定的。但必须满足两个硬性条件:
- 子
<details></details>必须是父<details></details>的**直接子元素**,不能包在<div>里 <li> <code><summary></summary>必须是父<details></details>的第一个子节点,否则 Safari 会忽略嵌套交互 - 嵌套层级越多,CSS 缩进越要靠
padding-left而非margin-left,否则点击热区偏移 - 别给
<summary></summary>加display: none或visibility: hidden,会导致语义丢失和键盘焦点失效
真正容易被忽略的是:多选本身没问题,但当某项内容高度动态(比如含<iframe></iframe>或第三方 widget)时,<details></details>收起并不会卸载其内部脚本或停止定时器。需要手动监听toggle并在open === false时清理资源,否则内存泄漏比样式问题更隐蔽。











