details和summary可原生实现响应式折叠面板,无需JS或框架;summary必须为details首个子元素,加open属性默认展开;CSS用max-height而非height做动画更可靠,需配合足够大的预设值及getBoundingClientRect()动态测量真实高度。

用 details 和 summary 最快实现响应式折叠面板
原生 HTML 就能做,不需要 JS 或框架。现代浏览器(Chrome 12+、Firefox 49+、Safari 6.1+、Edge 79+)都支持 details,它天生响应式——宽度缩小时内容自动收起,交互逻辑、焦点管理、语义化全部内置。
常见错误是手动写 div + JS 控制 display: none,结果屏幕阅读器无法识别可折叠结构,移动端点击区域小,还容易漏掉 aria-expanded 等无障碍属性。
实操建议:
-
details默认闭合,加open属性可默认展开:<details open><summary>标题</summary><p>内容</p> <p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p></details> -
summary内可放任意内联元素(图标、span、SVG),但不要嵌套button—— 它本身已是可聚焦、可按键触发的交互元素 - 用 CSS 选中展开状态:
details[open] > summary::after可替换默认三角箭头,避免用 JS 切换 class
CSS 控制折叠动画时为什么 max-height 比 height 更可靠
details 不支持直接对内容区域设 CSS 过渡(因为内部元素没有固定高度),硬加 transition: height 0.3s 会失效或跳变。正确做法是用 max-height 配合足够大的初始值,并确保内容高度不超过该值。
典型陷阱:设 max-height: 0 → max-height: 500px,但实际内容超 500px 就会被截断;或者用 overflow: hidden 却忘了给父容器设 overflow: visible(details 默认是 visible)。
实操建议:
- 给
details > *(除summary外所有子元素)设max-height: 0; overflow: hidden; transition: max-height 0.3s ease-in-out; -
details[open] > *设max-height: 500px(值需大于可能的最大内容高度,如含图片/动态文本,建议 800px 起) - 若内容含图片,确保图片加载完成后再计算高度 —— 但原生
details不触发resize事件,此时应改用 JS 实现(见下节)
需要动态高度动画?用 JS 监听 toggle 事件 + getBoundingClientRect()
当折叠内容高度不可预估(比如富文本、异步加载的评论列表),max-height 动画会失真。这时必须用 JS 测量真实高度并设置内联 style.maxHeight。
关键点在于监听 toggle 事件(不是 click),它在用户点击后、DOM 更新前触发,能准确读取即将展开/收起的内容尺寸。
实操建议:
- 用
details.addEventListener('toggle', e => { if (e.target.open) { const h = e.target.querySelector('div').getBoundingClientRect().height; e.target.style.setProperty('--target-height', h + 'px'); } }) - CSS 中用
details[open] > div { max-height: var(--target-height); },配合transition: max-height 0.3s ease - 避免在
toggle里直接调用offsetHeight—— 此时 DOM 尚未重排,返回值为 0;getBoundingClientRect()强制触发重排,拿到真实值
移动端点击无响应?检查 summary 是否被 pointer-events: none 或其他层遮挡
常见现象:桌面端正常,iOS Safari 或安卓 Chrome 点击没反应。大概率是 summary 上层有透明元素(比如伪元素、空 div、CSS Grid 的重叠区域),或父级设置了 touch-action: none。
另一个隐蔽原因是 summary 内用了 display: flex 但未设 align-items: center,导致点击热区偏移(尤其文字居中时,视觉中心 ≠ 可点击区域中心)。
实操建议:
- 用浏览器开发者工具的「元素选择器」悬停检查,确认点击时高亮的是
summary本身,而非其父或子节点 - 临时加
summary { outline: 2px solid red; }查看实际可点击范围 - 避免给
summary设position: relative后再用z-index—— 它可能脱离文档流,影响触摸事件捕获
max-height 值不会自动更新。这时候得重新监听 resize 或 MutationObserver,但别忘了节流 —— 频繁触发测量会卡顿。



















