details标签原生不支持transition,因浏览器切换open状态时不触发height/max-height等属性变化;需用预设max-height的CSS方案或监听toggle事件+scrollHeight的JS方案实现动画。

details 标签本身不支持 transition,任何直接对 height、max-height 或 opacity 添加 CSS 过渡的写法,在原生行为下都无效——这不是你写错了,而是浏览器根本不触发这些属性的变化。
为什么 details[open] 加 transition 没反应
浏览器切换 open 状态时,内部内容区没有 DOM 属性变化,也不修改 style.height 或 style.maxHeight;它只是开关显隐,不走 CSS 渲染流水线。所以:
-
details[open] { max-height: 500px; transition: max-height 0.3s; }→ 完全不生效 -
details > *:not(summary) { transition: max-height 0.3s; }→ 初始无max-height值,无法插值 - 哪怕手动加了
max-height: 0,没强制重排(reflow),过渡也起不来
纯 CSS 方案:用 :open + 预设 max-height
如果你能接受内容高度大致可控(比如筛选项固定、文本不超过 6 行),可以零 JS 实现平滑展开:
- 给内容容器(如
<div class="content">)设max-height: 0; overflow: hidden; - 在
details:open .content中设max-height: 400px;(值要略大于最大可能高度) - 加上
transition: max-height 0.25s ease, opacity 0.15s 0.05s ease; - 配合
details:open .content { opacity: 1; }和初始opacity: 0;提升观感 - 注意:Safari 16.4 之前不支持
:open的过渡触发,需降级为[open]写法
JS 动态方案:监听 toggle 事件 + scrollHeight
当内容含图片、动态插入或行高不可预估时,必须用 JS 读取真实高度并接管动画:
立即学习“前端免费学习笔记(深入)”;
- 监听
details.addEventListener('toggle', ...),比click更可靠(兼容键盘 Enter/Space) - 展开前先设
content.style.maxHeight = '0',再调用content.offsetHeight强制重排 - 再设
content.style.maxHeight = content.scrollHeight + 'px' - 收起时反向操作:先设目标高度,再重排,再设
'0' - Safari 中
scrollHeight可能读错(尤其图片未加载完),建议 fallback:getComputedStyle(content).height或加requestAnimationFrame延迟读取
容易被忽略的三个硬伤
即使代码写对,以下三点仍常导致动画卡顿、截断或点击失灵:
-
summary不是details的**第一个子元素节点**(中间有换行、空格或注释)→ Safari 直接禁用 toggle 行为 - 自定义箭头用了
summary::marker但没配summary::-webkit-details-marker→ Safari ≤15.6 图标消失且无回退 - 内容区里有
<video autoplay>或<iframe>→open=false后它们仍在运行,得手动pause()或src = ''



















