默认展开只需写open属性,不带等号、引号或值;JS应直接读写el.open布尔值;CSS用details[open]选择器;监听用toggle事件。

details默认展开只写open,多一个字符都错
直接加open属性就行,不带等号、不带引号、不带任何值:<details open></details>。这是唯一正确写法。
常见错误是写成<details open="false"></details>或<details open="true"></details>——这些写法浏览器全当“属性存在”,结果反而强制展开。HTML规范把open定义为布尔属性,只认“有没有”,不解析右边写了啥。
-
<details></details>→ 默认收起 -
<details open></details>→ 默认展开(唯一正确写法) -
<details open="0"></details>、<details open="banana"></details>→ 全部等效于展开(别这么写)
JS动态控制必须改el.open,不是setAttribute
用JS切换状态时,直接读写DOM元素的open属性,它返回布尔值,且与渲染状态实时同步。
写el.setAttribute('open', 'false')是最常踩的坑:这会让HTML属性存在,触发“存在即展开”,结果和你想的完全相反。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
- ✅ 正确:
el.open = true、el.open = false、console.log(el.open) - ❌ 错误:
el.setAttribute('open', 'false')、el.getAttribute('open')(返回字符串或null,无法反映真实状态) - ⚠️ 注意:
el.hasAttribute('open')和el.open不等价:初始没写open时两者都是false;但执行el.open = true后,hasAttribute仍返回false(HTML源码没变)
CSS响应展开状态只能用details[open]
想根据展开/收起状态改变样式,比如箭头方向或内容高度,必须用属性选择器details[open]。它能响应DOM属性变化,零延迟、原生支持。
- ✅ 正确:
details[open] summary::after { content: "▲"; } - ✅ 正确:
details:not([open]) .content { max-height: 0; overflow: hidden; } - ❌ 错误:
details[open="false"](浏览器根本不解析值)、details.open(class不存在)
监听状态变化只能用toggle事件
details没有change事件,click也不可靠:
- ✅ 正确:
el.addEventListener('toggle', () => console.log(el.open)) - ❌ 错误:
el.addEventListener('change', ...)→ 根本不会触发 - ❌ 错误:给
<summary></summary>绑click→ 干扰键盘(Enter/Space)和屏幕阅读器行为 - ⚠️ 注意:
toggle在状态变更后派发,此时el.open已是最新的布尔值;首次加载不触发
[open]选择器响应的是DOM属性变化(哪怕由JS设置),而hasAttribute()查的是HTML源码——这两条路径不同步,混用极易出错。


















