原生支持折叠但不自动互斥,需js监听toggle事件实现单开;默认无平滑动画,可用max-height+scrollheight模拟;兼容性要求高时应改用checkbox+css或button+aria方案。

用 <details></details> 实现零 JS 折叠面板,但别指望它自动互斥
现代浏览器(Chrome 12+、Firefox 49+、Safari 6.1+、Edge 79+)原生支持 <details></details>,点 <summary></summary> 就能展开/收起,键盘空格或回车也有效,自带 ARIA 语义和焦点管理——这是最轻量、无障碍友好的起点。
但它默认允许多开,不是“手风琴”;想单开必须加 JS 控制 open 属性。常见错误是误以为加了多个 <details></details> 就自动互斥,结果点第二个时第一个还开着。
-
<summary></summary>必须是<details></details>的第一个子元素,否则不生效 - 默认收起;加
open属性可默认展开:<details open></details> - Safari 15.4+ 才修复
<summary></summary>的 focus 样式 bug,旧版可能失焦 - 不能直接对
height: auto做 transition,所以原生无平滑动画
让多个 <details></details> 互斥:监听 toggle 事件,别用 click
要实现“点一个、其他关闭”,必须监听 toggle 事件——它在用户点击、空格、回车触发展开/收起时都会触发;click 会漏掉键盘操作,导致屏幕阅读器或键盘用户无法同步状态。
核心逻辑是:只在当前项 open === true 时,遍历同组所有 <details></details>,把非当前项的 open 属性移除(用 .removeAttribute('open'),别用 .open = false,后者会再触发一次 toggle)。
- 给所有面板加统一 class,比如
class="accordion-item",方便选择 - 动态插入的新
<details></details>需重新绑定,或改用事件委托(监听父容器上的toggle) - 不要在
<summary></summary>里放<button></button>或链接——点击会冒泡触发折叠;要么加event.stopPropagation(),要么把按钮移到<summary></summary>外、<details></details>内
加平滑动画:用 max-height + JS 测高,别硬写死 500px
想有 height 过渡效果,就得绕过 <details></details> 的限制,改用 <div> + <code>max-height + transition。关键陷阱是:直接写 max-height: 500px 容易截断长内容,或让短内容动画拖沓。
稳妥做法是 JS 在展开前读取目标元素的 scrollHeight,设为 max-height;收起时设为 0。注意 overflow: hidden 必须始终存在,否则动画中内容会溢出。
- 如果面板含
padding或margin,需在 JS 中一并计入,否则动画结束时布局跳变 - 用
getComputedStyle(el).height读不到auto高度,必须用el.scrollHeight - CSS 中避免用
height: auto过渡,它不触发重排动画,只会突变
需要多开、表单提交或兼容 IE?换 input[type="checkbox"] + CSS 兄弟选择器
如果项目要兼容 IE9+、支持多开、允许默认展开任意项、或希望状态能随表单提交,<details></details> 不够用,得退回到 input[type="checkbox"] 方案。
它纯 CSS 驱动,靠 :checked ~ .content 控制显隐,无需 JS。但结构约束强:checkbox 和目标 .content 必须同级、在同一父容器内;~ 匹配后续所有符合条件兄弟,+ 只匹配紧邻下一个。
-
<label></label>必须包裹<input>或用for绑定,否则点击无效 - 隐藏 checkbox 时别用
display: none,要用position: absolute; clip: rect(0 0 0 0)保交互 - 无障碍需手动补
aria-expanded和aria-controls,仅靠 CSS 类名无法被读屏软件识别
<details></details> 适合后台管理页或原型验证;生产环境若要求多开、动效、IE 兼容或严格无障碍,就得用 button+div+ARIA+JS 或 checkbox+CSS 方案。选哪个,取决于你愿意为兼容性和控制力多写几行 JS。











