details 元素是原生、语义化、无障碍的卡片折叠方案,需确保 summary 为 details 的首个子元素且不破坏其按钮语义;自定义箭头用 summary::before,禁用 list-style;如需高度动画或手风琴效果,则需 JS 配合 max-height 和 toggle 事件。

用 details + summary 实现最简卡片折叠
能直接用原生 HTML 解决,就别碰 JS。只要浏览器支持(Chrome 12+、Firefox 49+、Safari 12.1+、Edge 79+),details 就是卡片折叠的首选方案——它自带状态管理、键盘可访问(空格/回车触发)、屏幕阅读器语义正确,且不依赖任何外部代码。
常见错误是把 summary 套在 div 里,或让它不是 details 的第一个子元素。一旦顺序错,点击就完全没反应。
-
summary必须紧贴details开始标签后,中间不能有文本、注释或换行符(HTML 解析会把它当文本节点) - 默认收起;加
open属性可默认展开:标题
内容
- 内容区域可以放任意 HTML:
p、ul、img,甚至嵌套表单,但不要放script(执行不受控)
想加旋转箭头?用 summary::before 而不是 summary::marker
Safari 对 summary::marker 支持不稳定,尤其旧版本(15.4 之前)常忽略 content: "",导致图标消失又没 fallback。稳妥做法是统一用 summary::before 控制图标,并保留原生交互逻辑。
关键点在于:不能动 summary 的 display 或移除其按钮语义,否则键盘焦点和 ARIA 属性会失效。
- 先清掉默认箭头:
summary { list-style: none; } - 再补自定义符号:
summary::before { content: "▶"; margin-right: 8px; transition: transform 0.2s; } - 展开时旋转:
details[open] summary::before { transform: rotate(90deg); } - 别写
summary { display: block; }——这会让它退化成普通文本,失去可点击性和语义
需要平滑高度动画?放弃原生 details,改用 max-height + JS
details 不支持 height 或 max-height 过渡动画,浏览器硬编码了“瞬间切换”。真要向下展开的丝滑感,就得手动控制样式,此时已不属于原生方案范畴。
核心陷阱是设 max-height: 0 → max-height: auto:CSS 无法对 auto 做过渡。必须预估一个“足够大但不过分”的值,比如 500px,并配合 overflow: hidden。
- 初始状态:
.collapsible-content { max-height: 0; overflow: hidden; transition: max-height 0.3s ease-out; } - 展开时设为固定值:
max-height: 500px(不能是none或auto) - JS 只需切换 class:
el.classList.toggle("is-open"),不要操作style.display - 若内容高度差异大(比如含图片或异步加载文本),得在展开前用
scrollHeight动态读取并设max-height,否则动画会卡顿或截断
多个卡片要手风琴效果(单开)?监听 toggle 事件,别用 click
给每个 summary 绑 click 事件是错的——键盘用户按空格/回车不会触发,aria-expanded 也不会自动同步。正确入口是 details 元素上的 toggle 事件。
手风琴逻辑本质是:当前展开时,把所有兄弟 details 的 open 设为 false。注意别漏掉动态插入的卡片。
- 绑定事件到父容器更安全:
container.addEventListener("toggle", e => { if (e.target.matches("details")) { ... } }) - 关闭兄弟项用
e.target.parentElement.querySelectorAll("details"),再过滤掉自身 - 避免在
toggle回调里再调e.target.open = true——这会引发重复触发 - 如果用了 UI 库(如 Element Plus),它的
el-collapse可能已劫持原生行为,优先用库自己的 API,而非强行操作details
真正容易被忽略的是内容生命周期:收起的 details 里若有 video、iframe 或定时器,它们不会自动暂停或销毁。需要在 toggle 事件中手动检查 !e.target.open 并清理资源。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











