details 和 summary 标签原生支持点击展开收起,无需 JavaScript;details 为容器,summary 为唯一且首个子元素的标题行;默认收起,加 open 属性可默认展开;支持自定义箭头图标 via ::marker。

用 details 和 summary 最快实现点击展开
不用写 JS,原生 HTML 就能搞定。浏览器支持已很成熟(Chrome 12+、Firefox 49+、Safari 6+、Edge 79+),移动端也完全可用。
核心是这两个标签:details 是容器,summary 是可点击的标题行,其余内容默认收起:
<details> <summary>点击查看说明</summary> <p>这里是详细内容,初始不可见。</p> <p>支持任意 HTML 元素,包括列表、代码块、图片。</p> </details>
-
details默认是关闭状态;加open属性可默认展开:<details open> -
summary只能有一个,且必须是details的第一个子元素 - 点击
summary文本或其空白区域都会触发展开/收起,无需额外绑定事件 - 不支持嵌套动画(如淡入/滑动),如需过渡效果得配合 CSS + JS
想加箭头图标?用 CSS 控制 summary 的伪元素
浏览器默认在 summary 左侧显示一个三角形,但样式不可控。要自定义箭头(比如右向 → 或下向 ↓),得用 ::marker 或 ::before:
summary {
list-style: none; /* 先清掉默认三角 */
}
summary::marker {
content: "▶ "; /* 展开态箭头 */
}
details[open] summary::marker {
content: "▼ "; /* 收起态箭头 */
}-
::marker在 Chrome/Firefox/Edge 中稳定支持,Safari 15.4+ 开始支持 - 如果兼容旧 Safari(summary::before +
details[open]切换content - 避免用背景图或 SVG 图标做箭头——会破坏语义和屏幕阅读器识别
需要 JS 监听展开/收起动作?监听 toggle 事件
details 元素在用户点击时会触发 toggle 事件,不是 click,也不是 change:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
document.querySelector('details').addEventListener('toggle', function(e) {
if (this.open) {
console.log('已展开');
// 可在这里懒加载内容、发埋点、触发动画
} else {
console.log('已收起');
}
});- 该事件只在用户交互时触发,JS 修改
open属性不会触发它 - 不要监听
click:点击summary会先触发click,再触发toggle,逻辑易混乱 - 多个
details共存时,每个都要单独绑定,或者用事件委托(注意toggle不冒泡)
为什么不用 display: none + JS 切换?
手动控制 display 或 max-height 动画看似灵活,但实际问题不少:
- 可访问性差:屏幕阅读器无法感知内容是否“可展开”,
details自带aria-expanded和键盘支持(空格/回车切换) - 维护成本高:要自己处理焦点管理、过渡中断、多次点击竞争、初始状态同步
- 移动端体验打折:原生
details支持双指缩放内内容、滚动行为更自然 - SEO 更友好:
details内容始终在 DOM 中,搜索引擎可索引;而 JS 懒加载可能延迟收录
除非你明确需要滑动动画或与某个 JS 组件深度耦合,否则没必要绕开原生方案。
真正容易被忽略的是语义和可访问性——summary 文本必须准确描述下面内容,不能写“点击查看”,而应写“配置项说明”或“错误排查步骤”。这点比加个箭头重要得多。

















