details 和 summary 是原生可折叠组件,需确保 summary 为 details 的首个子元素且不颠倒嵌套顺序;open 为布尔属性,仅存在即生效;监听 toggle 事件响应状态变化,禁用 preventDefault;自定义样式须兼容 ::marker 并保留原生交互。

details 和 summary 是浏览器原生支持的折叠组件,不用写 JS 就能实现展开/收起,语义清晰、键盘可用、屏幕阅读器友好。
基础结构必须满足两个硬性条件
很多页面一加就失效,往往卡在这两点:
-
summary必须是details的第一个子元素,中间不能插其他标签(哪怕一个空格、或注释) -
details内部除summary外的内容,会自动被隐藏;但不能把details套在summary外面——顺序反了就完全不工作
正确写法示例:
<details>
<summary>常见问题</summary>
<p>这里的内容默认收起,点击标题才显示。</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill10560" title="生成HTML格式PPT"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20d79f23518.jpg" alt="生成HTML格式PPT" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill10560" title="生成HTML格式PPT">生成HTML格式PPT</a>
<p>从零开始创建惊艳、动画丰富且自包含的 HTML 演示文稿,或通过转换 PowerPoint 文件生成。当用户希望制作幻灯片、构建演示文稿、打造路演资料(pitch deck)、将 PPT/PPTX 转换为网页格式,或增强现有 HTML 演示文稿时,应使用此能力。该能力帮助用户通过视觉预览而非抽象选项来发掘自身审美偏好。</p>
</div>
<a href="/xiazai/skill10560" title="生成HTML格式PPT" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div>
</details>
控制默认展开用 open 属性,别写成 open="true"
open 是布尔属性,有它就展开,没它就收起。写成 open="true" 或 open="false" 都无效——浏览器只看是否存在该属性名。
- 默认展开:
<details open><summary>说明</summary>...</details> - JS 动态控制:
el.open = true或el.open = false,会立即触发重绘 - 注意:设置
open后再用 JS 改el.open,仍会触发toggle事件
监听展开收起动作要用 toggle 事件,不是 click
直接给 summary 绑 click 事件容易破坏原生行为(比如阻止默认、重复触发、干扰键盘操作),应该监听 details 元素上的 toggle 事件:
const details = document.querySelector('details');
details.addEventListener('toggle', () => {
console.log('当前状态:', details.open);
});
- 该事件在用户点击
summary、按空格/回车键、或 JS 修改open属性时都会触发 - 首次页面加载时不会触发,仅响应状态变化
- 不要在事件处理中调用
event.preventDefault()—— 它对toggle无效,且无意义
自定义箭头和样式要注意 marker 伪元素兼容性
浏览器默认在 summary 前加一个可旋转的小箭头,用 details[open] > summary::marker 可覆盖,但有坑:
-
::marker在 Safari 15.4+ 和 Chrome 110+ 才稳定支持,旧版需用summary::before+content模拟 - 不能用
display: none隐藏::marker,得用content: "" - 若要换图标,建议用 inline SVG 而非字体图标,避免缩放错位或加载失败
真正容易被忽略的是:所有样式增强都应在保障原生交互的前提下做,一旦加了 pointer-events: none 或覆盖了 summary 的点击区域,折叠功能就可能失灵。

















