details 元素配合 summary 可原生实现无障碍、无 js 的语义化折叠树,支持键盘操作与屏幕阅读器,需正确嵌套、自定义箭头与缩进,并为旧浏览器降级处理及关注性能与可访问性细节。

用 details 和 summary 实现语义化折叠树(无需 JS)
现代 HTML 原生支持树形折叠,details 是最轻量、无障碍友好的方案。它天然支持键盘展开/收起(Space/Enter)、屏幕阅读器识别,且不依赖 JS 就能工作。
常见错误是强行套用 div + CSS 类模拟折叠,结果丢失语义、无法键盘操作、SEO 不友好。
-
details默认闭合,加open属性可默认展开 -
summary必须是details的第一个子元素,否则渲染异常 - 嵌套时,子
details放在父summary后面(不是里面),否则点击会触发多层展开
<details><summary>一级节点</summary><details><summary>二级节点</summary><p>叶子内容</p> </details></details>
用 CSS 控制折叠箭头和缩进样式
浏览器默认的三角箭头样式不统一(Chrome 黑色实心,Firefox 灰色空心),且无层级缩进。需要手动覆盖:
- 用
summary::marker重置原生箭头(注意 Safari 17+ 才支持) - 用
details[open] > summary::after添加自定义图标(如 ▼ / ▶) - 通过
margin-left或padding-left模拟缩进,每层递增(例如 1rem、2rem) - 避免用
display: none隐藏summary,会导致键盘焦点丢失
summary::marker { content: ""; }
summary::after { content: "▶"; }
details[open] > summary::after { content: "▼"; }
details > details { margin-left: 1rem; }
兼容旧浏览器时 fallback 到 JS 控制的 class 切换
IE 完全不支持 details,Safari 12 及更早版本有 bug(open 属性不生效)。需检测支持性并降级:
- 用
"open" in document.createElement("details")判断原生支持 - 不支持时,给每个节点加
data-level标记层级,用 JS 绑定 click 切换is-openclass - CSS 中同时写两套规则:
details[open] {...}和.is-open {...} - 关键点:JS 降级后必须手动
tabindex="0"+keydown处理 Enter/Space,否则键盘不可用
处理大量节点时的性能与可访问性陷阱
当树超过 50+ 节点,直接渲染所有 details 会导致 DOM 膨胀、首屏卡顿;而过度懒加载又破坏语义结构。
- 不要用 JS 动态插入
details——会丢失初始折叠状态,且屏幕阅读器可能读取不全 - 对深层子节点,考虑用
loading="lazy"配合IntersectionObserver延迟渲染(仅适用于叶子内容,非summary) - 每个
summary必须有明确文本,禁止纯图标或空标签,否则 AT(辅助技术)无法朗读 - 展开/收起状态变化时,用
aria-expanded同步更新(原生details已自动处理,但 JS 降级时需手动维护)
真正难的不是写出来,而是让折叠状态在刷新后保持、在键盘导航中可靠、在不同 AT 下一致表达——这些细节比结构本身更消耗调试时间。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











