details/summary 是纯 HTML 折叠展开的唯一原生方案,需确保 summary 为 details 的首个子元素且非自闭合,open 为布尔属性,动画依赖 max-height 预估与 transition,兼容性需兜底,复杂交互须用 JS。

就是纯 HTML 折叠展开的唯一原生方案,不需要 JS、不依赖 CSS 框架,写对结构浏览器就自动响应。
details 标签必须这样写才生效
很多折叠失效,其实是结构错了——summary 必须是 details 的第一个子元素,且不能自闭合。
-
<summary>标题</summary> ✅ 正确:有开始和结束标签
-
<summary></summary> ❌ 错误:自闭合写法在多数浏览器里不触发折叠逻辑
-
<details><p>标题</p>
<summary>内容</summary></details> ❌ 错误:p 占了第一个子元素位置,summary 失效
-
<details open><summary>默认展开</summary><p>内容</p></details> ✅ 正确:open 是布尔属性,存在即生效,不要写 open="true"
想加滑动动画?max-height 是唯一靠谱方案
原生 details 只有显隐切换,没有滑动效果。要加动画,就得绕过它,自己用 CSS 控制 max-height。
立即学习“前端免费学习笔记(深入)”;
- 不能用
height: auto 配 transition,因为 auto 无法过渡
- 也不能用
display: none,它根本不可动画
- 正确做法:初始设
max-height: 0; overflow: hidden;,展开时设为一个足够大的值,比如 max-height: 500px;
- 必须配
transition: max-height 0.3s ease-in-out;,否则没动画
- 如果内容高度差异大(比如一段代码块 + 一张图),预估上限值宁大勿小,否则动画会提前截断
兼容性与可访问性别踩坑
虽然现代浏览器都支持 details/summary,但实际部署时几个细节直接影响体验。
- Chrome 12+、Firefox 49+、Edge 79+、Safari 6+ 支持,IE 全系不支持——若需兼容 IE,必须降级为 JS 方案
- 屏幕阅读器能识别
open 状态并播报“已展开/已折叠”,前提是结构合法;乱套的嵌套会破坏语义
-
summary::marker 可隐藏或替换三角图标,但 Safari 对它的支持不稳定,建议用 details[open] > summary::marker 加前缀控制
- 点击热区默认只覆盖
summary 文字区域,padding 不响应;如需扩大,加 display: block; width: 100%; 并确保父容器没 overflow: hidden
嵌套折叠或联动控制?原生能力到此为止
原生 details 不支持嵌套动画、不支持 JS 监听“正在展开中”这类中间状态,也不提供统一收起/全部展开按钮。
- 多个
details 同时展开?只能靠 JS 批量操作 open 属性,比如 document.querySelectorAll('details').forEach(d => d.open = true)
- 需要监听展开完成?用
toggle 事件:el.addEventListener('toggle', () => console.log(el.open)),但它不带过渡完成回调
- 嵌套
details 在部分浏览器(如旧版 Safari)里会丢失子项的交互,建议避免深层嵌套
- 如果内容含
pre 或代码块,注意 white-space: pre-wrap 和 max-height 冲突导致换行异常,可加 word-break: break-word 缓解
原生折叠看着简单,真正用稳的关键在于:结构零容错、动画靠预估值、兼容性靠兜底判断、复杂交互必须交还 JS。别指望一个标签解决所有问题,它只是个起点。
summary 必须是 details 的第一个子元素,且不能自闭合。<summary>标题</summary> ✅ 正确:有开始和结束标签<summary></summary> ❌ 错误:自闭合写法在多数浏览器里不触发折叠逻辑<details><p>标题</p>
<summary>内容</summary></details> ❌ 错误:p 占了第一个子元素位置,summary 失效<details open><summary>默认展开</summary><p>内容</p></details> ✅ 正确:open 是布尔属性,存在即生效,不要写 open="true"
details 只有显隐切换,没有滑动效果。要加动画,就得绕过它,自己用 CSS 控制 max-height。height: auto 配 transition,因为 auto 无法过渡display: none,它根本不可动画max-height: 0; overflow: hidden;,展开时设为一个足够大的值,比如 max-height: 500px;
transition: max-height 0.3s ease-in-out;,否则没动画details/summary,但实际部署时几个细节直接影响体验。open 状态并播报“已展开/已折叠”,前提是结构合法;乱套的嵌套会破坏语义summary::marker 可隐藏或替换三角图标,但 Safari 对它的支持不稳定,建议用 details[open] > summary::marker 加前缀控制summary 文字区域,padding 不响应;如需扩大,加 display: block; width: 100%; 并确保父容器没 overflow: hidden
details 不支持嵌套动画、不支持 JS 监听“正在展开中”这类中间状态,也不提供统一收起/全部展开按钮。details 同时展开?只能靠 JS 批量操作 open 属性,比如 document.querySelectorAll('details').forEach(d => d.open = true)
toggle 事件:el.addEventListener('toggle', () => console.log(el.open)),但它不带过渡完成回调details 在部分浏览器(如旧版 Safari)里会丢失子项的交互,建议避免深层嵌套pre 或代码块,注意 white-space: pre-wrap 和 max-height 冲突导致换行异常,可加 word-break: break-word 缓解



















