<details>默认展开只需写open属性,不带等号或值;JS操作用el.open读写布尔值;CSS用details[open]选择器;监听状态用toggle事件。

details默认展开只写open,多一个字符都错
想让<details>一打开就展开,直接加open属性就行,不带等号、不带引号、不带任何值。这是唯一正确写法。
-
<details open><summary>标题</summary><p>内容</p></details>→ 正确,默认展开 -
<details open="false">、<details open="">、<details open="0">→ 全部强制展开(因为属性存在) -
<details>→ 默认收起,什么也不用写
HTML 规范把open定义为布尔属性,浏览器只检测它“有没有”,不解析右边的值。写错会反向生效,这是最常翻车的地方。
JS动态控制open状态必须读写el.open,不是setAttribute
要用 JavaScript 切换状态,直接操作 DOM 元素的open属性,它返回布尔值,且与渲染状态实时同步。
- ✅ 正确:
el.open = true、el.open = false、console.log(el.open) - ❌ 错误:
el.setAttribute('open', 'false')→ 属性被写入,触发“存在即展开” - ❌ 错误:
el.getAttribute('open')→ 返回字符串或null,无法反映真实状态 - 推荐切换方式:
el.toggleAttribute('open'),语义清晰且同步 DOM 与 HTML 属性
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→open不是 class,不存在这个类名
注意:details[open]选择器响应的是 DOM 属性变化(哪怕由 JS 设置),而hasAttribute()查的是 HTML 源码——这两条路径不同步,混用极易出错。
监听展开/收起变化只能用toggle事件
<details>没有change事件,click也不可靠。用户点击<summary>、键盘操作(空格/回车)或 JS 修改el.open,都会触发toggle事件,此时读el.open才是最新值。
- ✅ 正确:
el.addEventListener('toggle', () => console.log(el.open)) - ❌ 错误:
el.addEventListener('change', ...)→ 根本不会触发 - ❌ 错误:给
<summary>绑click→ 干扰键盘行为和屏幕阅读器,且无法捕获 JS 触发的状态变更
toggle在状态变更后派发,此时el.open已是最新的布尔值;首次加载不触发,这点容易被忽略。



















