原生 是最轻量稳妥的折叠方案,语义正确、无障碍友好;但不支持嵌套、动画及复杂布局,需 JS 方案补足 scrollHeight 测量与状态管理。

用 <details></details> + <summary></summary> 最快实现原生折叠
不需要写一行 JS,语义正确、键盘可访问、屏幕阅读器友好——这是最轻量也最稳妥的起点。
关键限制必须清楚:<summary></summary> 必须是 <details></details> 的第一个子元素;否则点击无效。默认收起,加 open 属性即默认展开。
<details open><summary>标题</summary><p>内容</p></details>- Safari 对
summary::marker支持差,想换图标别只靠content: "",得用summary::before+transform模拟旋转 - 不支持嵌套
<details></details>:部分浏览器会丢弃内层状态,多级折叠必须换 JS 方案
要加平滑高度动画?必须放弃原生 <details></details> 行为
原生 <details></details> 不支持 transition,浏览器自己控制显隐,无法做 height 渐变或 fade 效果。真要动画,就得手动接管状态和样式。
立即学习“前端免费学习笔记(深入)”;
核心难点是高度自适应:不能对 height: auto 做过渡,只能靠 max-height + scrollHeight 测量。
- 初始状态设
max-height: 0; overflow: hidden;,并加transition: max-height 0.3s ease-in-out - JS 点击时读取目标元素的
scrollHeight,赋给max-height;收起时设回0 - 收起后记得清空
max-height再设overflow: hidden,否则可能残留滚动条 - 内容含
<img alt="HTML文字折叠展开怎么弄?完整制作流程" >或异步加载时,展开后需调用offsetHeight强制重排,确保scrollHeight准确
JS 切换状态时,别只靠 classList.toggle
仅切类名容易和视觉脱节:按钮文案没同步、ARIA 属性缺失、焦点管理被忽略——这些在无障碍测试里直接失败。
更可靠的做法是把状态存在 dataset 里,文案和属性都由 JS 统一驱动。
- 用
el.dataset.expanded = "true"记录状态,比查classList.contains("active")更稳定 - 按钮文案统一由 JS 控制:
btn.textContent = isExpanded ? "收起" : "展开" - 必须加
aria-expanded和aria-controls,例如:<button aria-expanded="false" aria-controls="panel-1"></button> - 如果按钮在
<form></form>里,点击时先event.preventDefault(),避免意外提交
长文本里有浮动、绝对定位或 flex 子项?scrollHeight 会不准
容器内部若用了 float、position: absolute 或 display: flex,scrollHeight 可能低估真实高度,导致展开后底部被截断。
这不是 JS 错,是 CSS 布局干扰了高度计算逻辑。
- 确保折叠容器自身是
display: block(默认即可),不要设flex或grid - 子元素避免
float和position: absolute;如有flex子项,加align-items: flex-start防止基线对齐拉高容器 - 极端情况可临时加
contain: layout隔离布局影响,但注意兼容性(IE 不支持)
<details></details> 足够应付 FAQ、帮助文档这类静态结构;一旦涉及动画、多面板联动、动态内容或复杂子布局,就得切到 JS + max-height 方案——而那个 scrollHeight 测量时机,往往是上线前最后一刻才发现不对的地方。



















