details标签加open属性即可默认展开,浏览器只检测属性存在与否;正确写法是,错误写法如open="false"仍会展开;js操作应使用el.open=true/false或toggleattribute,css需用details[open]选择器。

details标签加open属性就能默认展开,别写值
直接在<details></details>标签上写open即可,默认展开;浏览器只检测这个属性是否存在,不解析等号右边的任何内容。
常见错误写法:<details open="false"></details>、<details open=""></details>、<details open="0"></details>——这些全部等效于展开,因为属性名出现了。
- 正确默认展开:
<details open><summary>标题</summary><p>内容</p></details>
- 正确默认收起:
<details><summary>标题</summary><p>内容</p></details> - 服务端渲染或静态 HTML 场景下,这是最轻量、最可靠的方式,无 JS 依赖
JavaScript 动态设 open 状态,必须操作 DOM 属性,不是 setAttribute
el.open = true 或 <code>el.open = false 才是正确写法;用 setAttribute('open', ...) 会把属性写进 HTML,导致“存在即展开”,哪怕你传的是 "false"。
容易混淆的点:el.hasAttribute('open') 查的是原始 HTML 字符串,而 el.open 是当前 DOM 状态,两者不同步。
- 初始没写
open:两者都是false - 执行
el.open = true后:el.open变true,但hasAttribute仍为false - 推荐切换方式:
el.toggleAttribute('open'),语义清晰且自动同步 HTML 和 DOM
CSS 响应展开状态只能用 details[open] 选择器
不能用 details[open="true"] 或 details:not([open]) 这类带值的写法——open 是布尔属性,浏览器根本不解析它的值。
想控制箭头旋转、内容显隐、边框颜色等,都得靠这个选择器:
details summary::after {
content: "▼";
transition: transform 0.2s;
}
details[open] summary::after {
content: "▲";
transform: rotate(180deg);
}
注意:details[open] 匹配的是 DOM 中实时的 open 布尔值,哪怕这个值是 JS 设置的,CSS 也能响应,但前提是元素已挂载且样式表已加载。
动画实现时,open 属性本身不触发 transition
open 属性只是个开关信号,浏览器对 <details></details> 的原生展开/收起是硬切换,没有过渡效果。要加动画,必须绕过它,用 max-height + overflow 模拟。
关键细节:
- 初始设
.content { max-height: 0; overflow: hidden; transition: max-height 0.3s; } - 在
toggle事件里读scrollHeight,但得先确保元素可见(display: block),否则返回0 - 展开逻辑要分两步:先设目标
max-height→ 下一帧再设el.open = true;收起则反过来 - localStorage 恢复状态必须在动画初始化前完成,否则
el.open = true会跳过你的 CSS 过渡
最易被忽略的是 scrollHeight 读取时机和 toggle 事件里 DOM 渲染的异步性——状态变了,但样式还没应用,直接设 height 容易错位或闪动。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











