details 折叠功能无需 JS,但需确保 summary 是 details 的首个子元素、用 summary::before 自定义箭头、通过 open 属性控制状态、手动暂停内部媒体,并注意 iOS Safari 兼容性及表单同步。

details 标签本身就能实现折叠,不需要 JS,但写错结构、加错 CSS 或忽略兼容性细节,就会点不动、不收起、图标错位甚至在 Safari 里默认展开关不掉。
summary 必须是 details 的第一个子元素
这是最常踩的坑。只要 summary 被 <p></p>、<div> 或其他块级标签包裹,或者它前面有空白文本节点,Safari 和旧版 Chrome 就可能完全忽略点击逻辑。<ul>
<li>✅ 正确:<code><details><summary>标题</summary><p>内容</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20d3191a227.jpg" alt="DeepBI DHTML 页面生成器" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器">DeepBI DHTML 页面生成器</a>
<p>生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力:
- 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面;
- 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”;
- 提及位于 `apps/console/src/featur</p>
</div>
<a href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div>
<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></details>
<details><div><summary>标题</summary></div>
<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></details>
<details><!-- 注释或空格 --><summary>标题</summary></details>
DOM 解析时的“第一个子节点”必须是 summary 元素节点,不能是文本节点(包括换行、空格)。
自定义箭头必须用 summary::before,别碰 ::marker
::marker 在 Safari ≤15.6、部分 Edge 和旧 Firefox 中不生效;::-webkit-details-marker 又只限 WebKit。统一用 summary::before 才能跨浏览器稳定显示和旋转。
- 先清空原生图标:
summary { list-style: none; } - 再加自定义图标:
summary::before { content: "▶"; margin-right: 6px; transition: transform .2s; } - 展开时旋转:
details[open] > summary::before { transform: rotate(90deg); } - 避免给
summary设display: inline-block或float,会破坏点击热区
JS 控制必须操作 open 属性,不是 style.display
直接改 style.display = 'block' 看似有效,但会绕过浏览器内置状态管理:屏幕阅读器读不出当前是否展开,toggle 事件不触发,键盘 Enter / Space 也无法切换。
- ✅ 正确切换:
el.open = !el.open或el.toggleAttribute('open') - ✅ 监听变化:
el.addEventListener('toggle', () => console.log(el.open)) - ❌ 错误写法:
el.style.display = el.open ? 'none' : 'block' - iOS Safari ≤15.4 不支持
open属性初始值,需 JS 补:if ('open' in el && !el.hasAttribute('open')) el.open = false
折叠后的内容仍在运行,关键逻辑要手动暂停
details 只控制显隐,不暂停内部脚本、视频、音频或 iframe。比如折叠区域里有个 <video autoplay></video>,收起后依然在播放、消耗带宽。
- 监听
toggle事件,在!el.open时手动.pause()、.remove()或.src = '' - 表单中用
details包裹字段时,注意它不参与提交——需要同步状态得额外加<input type="hidden"> - 服务端渲染页面时,若靠 JS 设置
open,可能出现“先闪一下收起再展开”,建议用 CSS 配合:not([open]) > *:not(summary)提前隐藏


















