<details>原生支持折叠展开,语义正确且无障碍友好;<summary>必须为首个子元素,漏写或错位将失效;默认收起,加open属性可默认展开;支持嵌套与任意HTML内容;IE不支持但现代浏览器全覆盖;样式需用list-style:none+::after模拟箭头并监听[open]做旋转动画;禁用height/overflow以免破坏过渡;避免<summary>内嵌<button>或<a>,表单控件需保持tab可达。

用 <details> 和 <summary> 实现折叠面板,不用 JS
HTML 原生就支持折叠展开,不需要写一行 JavaScript。<details> 是容器标签,<summary> 是点击区域,浏览器自动处理展开/收起状态和箭头图标。这是最轻量、语义正确、无障碍友好的方案。
常见错误是把 <summary> 放在 <details> 外面,或漏掉 <summary> —— 这会导致内容始终可见,且无法触发折叠。
-
<details>默认收起,加open属性可默认展开:<details open> -
<summary>必须是<details>的第一个子元素,否则无效 - 里面可以放任意 HTML 内容(
<p>、<ul>、甚至嵌套另一个<details>) - 不支持 IE,但 Chrome/Firefox/Safari/Edge 全部原生支持(2026 年已无兼容顾虑)
<details> 的样式控制:怎么改箭头、颜色、动画
浏览器默认给 <summary> 加了小三角,但不能直接用 CSS 伪元素覆盖它;要隐藏原生箭头,得用 list-style: none + 自定义 ::marker 或背景图。
关键点:Chrome 和 Firefox 对 ::marker 支持不一致,稳妥做法是用 display: flex + ::after 模拟箭头,并监听 [open] 属性做旋转动画。
立即学习“前端免费学习笔记(深入)”;
- 移除默认箭头:
summary { list-style: none; } - 添加自定义图标:
summary::after { content: "▶"; transition: transform 0.2s; } - 展开时旋转:
details[open] summary::after { transform: rotate(90deg); } - 注意:不要对
<details>设置height或overflow,会破坏原生过渡动画
替代方案:为什么别用 <div> + JS 手动实现
新手常想“自己用 <div> 控制 display: none/block”,这看似灵活,实则埋坑:
- 失去语义:屏幕阅读器无法识别这是可交互的折叠区域,无障碍失败
- 状态同步难:JS 需手动管理 open/close 状态、焦点、键盘操作(Enter/Space 键响应)
- SEO 不友好:搜索引擎可能忽略 JS 动态显示的内容
- 多实例易出错:每个面板都要单独绑定事件、维护状态变量,代码冗余
- 移动端手势支持弱:原生
<details>自带触摸优化,手写 JS 很难做到同等体验
实际使用时容易被忽略的细节
折叠面板不是“写了就能用好”的功能,几个真实项目里反复踩过的点:
-
<summary>里别放<button>或<a>—— 会触发双重点击行为,且破坏语义 - 如果内容含表单控件(如
<input>),确保它们在收起状态下仍可被 tab 键访问(<details>默认保持 tabindex 可达) - 服务端渲染时,避免在
<details>内部做条件渲染逻辑,否则客户端 hydration 可能错乱 - 不要用
!important强行覆盖summary::marker,Firefox 目前不支持该伪元素样式化



















