是原生语义化标签,需包含 子元素作为触发区,支持 open 布尔属性控制初始状态,通过 toggle 事件监听展开/收起,兼容性需 polyfill,css 可用 ::marker 定制箭头。

details 标签的基本结构和默认行为
<details></details> 是原生语义化标签,浏览器默认提供展开/收起交互,不需要 JS 就能工作。它必须包含一个 <summary></summary> 子元素作为触发区域,其余内容为折叠区。
关键点:如果省略 <summary></summary>,部分浏览器(如 Safari)会显示默认箭头文字(“Details”),但不可点击;Chrome 会渲染为空白可点击区域——行为不一致,务必显式写上。
-
<details open></details>可设初始展开状态,open是布尔属性,有即真,无需赋值 -
<summary></summary>内可嵌套任意行内元素,甚至<span></span>或图标,但避免放<div> 等块级元素(会破坏语义和样式流) <li>不支持 CSS 的 <code>:has()选择器直接检测展开态(旧版 Safari 不支持),稳妥做法是监听toggle事件或用 JS 操作open属性 - 移除默认箭头:
summary::marker { content: "" } - 自定义展开/收起图标:
details[open] summary::after { content: "−"; }+summary::after { content: "+" } - 折叠区内容默认有 top margin(来自
<summary></summary>的 margin-bottom),重置时建议统一设margin: 0避免跳动 - 监听写法:
document.querySelector('details').addEventListener('toggle', (e) => { console.log(e.target.open) }) -
e.target.open是当前最终状态(true=已展开),不是切换前的状态 - 不要在
toggle回调里再调用e.target.open = !e.target.open,会造成无限循环 - 动态加载内容?在
toggle事件里判断!e.target.open(即刚收起)时可清理资源,比如暂停视频、销毁图表实例 - 表单控件(如
<input>)放在<details></details>内无问题,但 autofocus 在收起状态下不会生效,展开后需手动.focus() - 无障碍方面:
<summary></summary>自动获得role="button"和aria-expanded,无需额外标注
用 CSS 控制展开箭头和样式
浏览器默认在 <summary></summary> 前加一个三角形箭头,可通过 ::marker 伪元素控制(Chrome/Firefox 支持,Safari 15.4+ 支持)。更兼容的方式是隐藏原生箭头,用 background-image 或 ::before 替代。
注意:直接对 <summary></summary> 设置 list-style: none 无效,必须用 ::marker { content: "" } 或 appearance: none(后者在 Safari 中需加前缀)。
监听 toggle 事件实现动态逻辑
<details></details> 元素会触发 toggle 事件(不是 click),只要用户点击 <summary></summary>、或 JS 修改 open 属性都会触发。这是获取展开/收起状态变更的唯一可靠方式。
常见误操作:绑定 click 到 <summary></summary> 上,但无法捕获通过 JS 设置 open = true 的场景,且在某些浏览器中可能重复触发。
与 JavaScript 交互时的兼容性和陷阱
IE 完全不支持 <details></details>,Edge 12–18 仅部分支持(无 toggle 事件)。若需兼容,得用 polyfill(如 details-polyfill)或降级为 <div> + JS 控制 class。
<p>另一个易忽略点:当 <code><details></details> 内容含第三方组件(如图表库、视频播放器),首次展开时 DOM 才挂载,需确保这些组件在 toggle 事件中初始化,而非页面加载时就找元素。











