原生 元素足以满足90%折叠需求,语义化、无障碍、无需JS/CSS动画;错误做法是手动控制display或max-height,应优先使用其原生能力并合理定制样式。

直接用 <details></details> 和 <summary></summary> 就够了
90% 的折叠卡片需求,不需要写 JS、不需手写 CSS 动画、也不用引入第三方库。HTML5 原生的 <details></details> 就是专为这事设计的语义化元素,浏览器原生支持状态切换、键盘导航(空格/回车触发)、屏幕阅读器识别,且自带方向翻转的三角图标。
常见错误是手动监听 click + 切换 display 或 max-height —— 这不仅冗余,还会破坏可访问性,Safari 15.4+ 或某些安卓 WebView 下还容易状态不同步或动画卡顿。
-
<summary></summary>必须是<details></details>的**第一个子元素**,否则折叠逻辑失效,部分浏览器会忽略后续内容 - 默认收起;加
open属性可默认展开:<details open><summary>标题</summary><p>内容</p></details> - 不要给
<details></details>设height: 0或overflow: hidden,这会干扰 Safari 的展开行为 - 样式定制优先用
details[open] > summary::marker控制箭头,而不是appearance: none或list-style: none粗暴清除
需要平滑滑动动画?用 max-height + transition
原生 <details></details> 只有显隐切换,没有“滑出”效果。若 UI 要求视觉上渐进展开(比如开发者门户里的 API 概览卡片),就得自己控制高度过渡。
立即学习“前端免费学习笔记(深入)”;
关键点不是“怎么动”,而是“怎么不让它崩”:CSS 中 height: auto 无法参与过渡,display: none 也不能动画,唯一可靠路径是 max-height。
- 初始状态设
max-height: 0; overflow: hidden; - 展开态设一个足够大的值,比如
max-height: 500px;(不能写auto) - 必须配
transition: max-height 0.3s ease-in-out;,否则无动画 - 内容高度不确定时,预估上限值比硬写死更稳妥;过大(如
9999px)可能导致动画末尾轻微卡顿 - 避免用
position: absolute包裹折叠内容——它脱离文档流,容器高度塌陷,卡片下方元素会上移错位
嵌套或复杂结构下,<details></details> 仍可用但要注意边界
比如在表格行内放折叠项、或卡片里嵌套多个 <details></details>,只要 DOM 结构合规,原生行为依然有效。但几个边界情况容易踩坑:
- 不要把
<details></details>直接塞进<table> 内部(如 <code><tr> 下),应包裹在 <code><td> 里,否则渲染异常 <li>多个 <code><details></details>并列时,别共用同一个 JS 控制逻辑(比如统一querySelectorAll('details')+toggle()),容易误触;推荐绑定到具体父容器再操作 - 若需禁用某张卡片的折叠功能,不要加
disabled(无效),而是移除其<summary></summary>,或用event.preventDefault()阻止默认行为 - 自定义
<summary></summary>布局时(如 flex 排版),务必测试 Tab 键能否聚焦到它——否则键盘用户无法操作 - 最简降级:把
<details></details>当普通<div> 渲染,所有内容始终可见(即 fallback to static content) <li>不建议用 JS 模拟原生行为(比如监听 click + 切换 class + 手动控制 <code>max-height),维护成本高,且在旧 WebView 下仍有状态不同步风险 - 如果必须动态交互,优先选轻量方案:用
<input type="checkbox">+:checked+ sibling combinator 实现 CSS-only 折叠,零 JS、无障碍基础尚可 - 所有方案中,
aria-expanded和aria-controls属性该加还得加,尤其当内容区有 id 时
兼容 IE?降级方案别强行“模拟”
IE 完全不支持 <details></details>,但 2026 年绝大多数项目已无需支持 IE。真要兼容,重点不是“做出一样效果”,而是“保证内容可读”:
真正难的不是让卡片动起来,而是让动的过程不破坏语义、不丢焦点、不卡在某个浏览器里——原生 <details></details> 已经帮你绕过了大部分坑,别轻易重造轮子。



















