details标签是唯一真正纯CSS可落地的折叠面板方案,无需JS即可切换状态、支持键盘操作、自动同步aria-expanded且语义正确;其他方案存在可访问性硬伤或行为不可靠问题。

details 标签是唯一真正“纯 CSS”可落地的折叠面板方案——它不需要 JS 就能切换状态、支持键盘(Space/Enter)、自动同步 aria-expanded,且语义正确。其他所谓“纯 CSS”方案(如 checkbox + :checked 或 max-height 过渡)都存在可访问性硬伤或行为不可靠问题。
用 details 实现可访问、可动画的折叠面板
原生 details 默认无动画,但可通过监听 toggle 事件 + 动态设置 max-height 补上平滑过渡,同时保留所有无障碍能力。
- 必须包裹内容区域(除
summary外的子元素),不能直接对details自身设max-height - 展开前先读取内容区
scrollHeight,设为内联max-height;收起时先设为当前高度,再setTimeout(() => el.style.maxHeight = '0')触发重排 -
summary内部不要用display: inline元素撑开点击热区——它只响应文字和::marker区域;可靠做法是给summary设display: block+padding,并确保父级details没有overflow: hidden - 禁用默认箭头统一用
summary::marker { content: "▶"; },展开时用details[open] summary::marker { content: "▼"; };Safari 16.4+ 支持,旧版需在summary里手动加<span class="icon"></span>并用 JS 切换旋转类
max-height 过渡值怎么设才不翻车
设成 max-height: 500px 或 30em 是常见错误:内容少时收起后留白,内容多时被截断。安全值取决于你内容的典型高度范围。
- 若内容高度较稳定(如 FAQ 条目 ≤ 3 行文本),用
max-height: 120px(≈ 3 行 × 字体行高 × 1.5)足够 - 若含图片或动态段落,保守上限建议
max-height: 600px;超过此值的面板应改用 JS 动态测量 - 永远配
overflow: hidden——漏掉它,动画过程中内容会溢出遮挡相邻元素 - 避免
transition: all;显式写transition: max-height 0.3s ease, opacity 0.3s ease,防止意外触发布局重排
为什么别碰 checkbox + :checked 方案
它看起来“纯 CSS”,但实际在真实项目中会踩三个坑:
- 无法聚焦:屏幕阅读器和键盘用户无法用 Tab 进入该控件,
label绑定的input不是语义化的交互控件 - 状态不可控:刷新页面后 checkbox 状态丢失,且无法通过 JS 安全地同步外部状态(比如从 URL 参数恢复展开项)
- 移动端点击失效:iOS Safari 对隐藏 checkbox 的 label 点击热区识别不稳定,尤其在 fastclick 或 scroll 后
手风琴模式(互斥展开)必须用 JS
details 原生不支持手风琴逻辑,但实现非常轻量——监听所有 details 的 toggle 事件,然后遍历关闭其他非当前项即可。
立即学习“前端免费学习笔记(深入)”;
关键点:不要用 querySelectorAll("details:not(:first-child)") 这类静态选择器去批量操作,而应在事件回调里用 event.target 精准定位当前触发项,再排除它本身。否则在动态增删面板时容易误关/漏关。


















