用 details 和 summary 实现点击展开是最轻量、原生、无障碍友好的方案,无需 JS 即可工作,现代浏览器均支持;details 为容器,summary 必须是其首个子元素且不可嵌套交互元素,CSS 可通过 summary::marker 自定义箭头。

怎么用 details 和 summary 实现点击展开
这是最轻量、原生、无障碍友好的方案,不需要 JS 就能工作,现代浏览器(Chrome 12+、Firefox 49+、Safari 6.1+、Edge 79+)都支持。
常见错误是直接套用 div + JS 模拟,结果语义缺失、屏幕阅读器读不出、SEO 不友好、移动端点透或失焦。
-
details是容器,自带折叠状态(open属性控制默认展开) -
summary必须是details的第一个子元素,点击它才触发切换 - 不要在
summary里嵌套button或a,会干扰默认行为 - 想自定义箭头?用 CSS 覆盖
summary::marker,别删掉summary
点击查看配置项
这里是隐藏内容,支持任意 HTML 元素。
为什么不用 JS 手动控制 display 或 height
手动 JS 控制展开收起看似灵活,实际踩坑密集:动画卡顿、过渡中断、焦点管理缺失、键盘无法空格/回车触发、aria-expanded 同步遗漏、服务端渲染时状态不一致。
立即学习“前端免费学习笔记(深入)”;
尤其在 React/Vue 等框架中,用 useState 控制 display: none,会导致 DOM 频繁销毁重建,影响性能和表单控件状态(比如输入框内容丢失)。
- 原生
details自动处理aria-expanded、键盘交互(空格/回车)、焦点返回 - CSS 过渡需配合
details[open] > *+max-height或opacity,不能只靠display - 若必须用 JS(如兼容 IE),优先封装成自定义元素(
custom-details),而非裸写toggle()函数
details 在 Safari 和旧版 Edge 的表现差异
Safari 15.4 之前不支持 details 的 CSS 动画,open 切换是硬切;旧版 Edge(
不要试图用 JS 检测 details 支持再降级,而是用渐进增强思路:默认按展开渲染,再用 @supports (display: details) 或 document.createElement('details').open !== undefined 加载增强逻辑。
- 检测支持性推荐用
'open' in document.createElement('details'),比 UA 判断可靠 - 如果项目必须支持 IE11,用
details-polyfill库,但注意它会注入额外 DOM 节点,可能影响样式继承 - Safari 中
summary::marker无法用content替换,只能用transform: rotate()控制箭头方向
如何让展开区域有平滑高度动画
原生 details 不提供开启动画的 API,但可以通过 CSS 组合实现视觉平滑效果,关键是绕过 height: auto 无法过渡的限制。
- 给
details[open] > *设置max-height+overflow: hidden,并配transition: max-height 0.3s ease - 预估最大高度(比如
max-height: 500px),太小会截断,太大动画拖沓 - 更稳妥的做法是用
opacity+transform: scaleY(),配合visibility: hidden控制可访问性 - 避免对
details本身设height或min-height,会破坏内部布局流
details[open] > * {
opacity: 1;
transform: scaleY(1);
transition: opacity 0.2s, transform 0.2s;
}
details > * {
opacity: 0;
transform: scaleY(0);
transform-origin: top;
visibility: hidden;
}
details[open] > * {
visibility: visible;
}细节上,summary 的点击区域、键盘焦点管理、以及服务端首次渲染时的 open 状态同步,是最容易被跳过的三个点。











