是专为可折叠内容设计的原生语义化标签,自带状态管理、键盘操作(空格/回车)及屏幕阅读器支持,无需 js 即可工作;它比 aria 模拟更轻量可靠,但需确保 为 的唯一首个子元素,不支持嵌套,样式受限于 ::marker,手风琴效果需 js 控制 open 状态以实现单开联动,降级应保证内容始终可见而非依赖 js 补救,语义核心在于真实反映“可选展开的细节”关系。

用 <details></details> 和 <summary></summary> 实现语义化折叠面板
原生 <details></details> 标签就是为可折叠内容设计的,自带展开/收起状态、键盘可访问(空格/回车触发)、屏幕阅读器支持,无需 JS 就能工作。它比用 <div> + ARIA 模拟更轻量、更可靠。
<p>常见错误是把 <code><summary></summary> 写成多个或放在错误位置——它必须是 <details></details> 的**第一个子元素**,且只能有一个:
<details><summary>常见问题</summary><p>这里是折叠内容……</p> </details>
- 默认收起,加
open属性可默认展开:<details open></details> - 不支持嵌套
<details></details>(部分浏览器会降级处理,但行为不一致) - 样式受限:
<summary></summary>前的三角图标无法用 CSS 完全重置(需用::marker或隐藏后自定义)
手风琴组件该不该用多个 <details></details>?
可以,但要注意交互逻辑冲突。多个独立 <details></details> 默认互不影响,而典型手风琴要求「一次只展开一个」——这必须靠 JS 控制 open 属性,否则语义正确但行为不符需求。
实操建议:
- 若只需基础折叠(如 FAQ 列表),直接并列多个
<details></details>,零 JS - 若要手风琴效果(单开、联动关闭),保留
<details></details>结构,但用 JS 监听toggle事件,手动管理其他项的open状态 - 避免用
display: none强制隐藏内容——这会让屏幕阅读器跳过,应依赖原生open控制可见性
为什么不用 <section></section> + ARIA 模拟?
有人用 <section aria-expanded="false"></section> 配合 JS 实现,看似灵活,但实际埋了坑:
- 键盘操作需自行实现:Tab 进入、空格切换、方向键导航都得手写
- ARIA 属性易出错:
aria-controls、aria-labelledby必须严格配对,漏写或 ID 错误会导致读屏器静默 - 状态同步脆弱:JS 报错或未加载时,UI 和 ARIA 状态立刻脱节
- 移动端双击放大等默认行为可能被意外禁用
除非需要高度定制动画或兼容 IE(已无必要),否则没必要放弃 <details></details> 的原生保障。
<details></details> 的兼容性和降级处理
现代浏览器全支持,包括 Safari 12.1+、Chrome 12+、Firefox 49+。iOS Safari 从 12.2 开始支持,基本覆盖当前主力设备。
真正要小心的是降级逻辑:
- 不要用
@supports (display: details)——CSS 不支持该特性查询 - 检测可用性应通过 JS:
'open' in document.createElement('details') - 降级方案不是“改用 div”,而是让内容始终可见(即不隐藏),再用 JS 增强折叠能力
- 服务端渲染时,避免在不支持环境里输出
<details></details>后又靠 JS 补救——结构已错,语义就丢了
语义化不是加标签就完事,关键在结构是否真实反映内容关系。一个 FAQ 页面里,每个问题确实是「可选展开的细节信息」,<details></details> 就是它的自然表达;硬套 <section></section> 反而模糊了这个意图。











