details[open] summary旋转动画必须显式声明常态transform值,否则无过渡;需同时隐藏原生marker、设置transform-origin,并避免JS干扰CSS动画。

details[open] summary 的 transform 旋转必须显式声明初始值
只在 details[open] summary 里写 transform: rotate(90deg) 是不够的,浏览器不会自动补全未声明的初始状态,结果就是点击时箭头“啪”一下跳转,没有过渡动画。必须让常态(收起态)也带明确的 transform 值。
-
summary默认是 inline 元素,无需额外设display,但必须加transition: transform 0.2s ease - 常态(未展开)写:
summary { transform: rotate(0deg); } - 展开态写:
details[open] summary { transform: rotate(90deg); } - 旋转中心点建议统一设为
transform-origin: 50% 50%,避免小图标偏移或抖动
隐藏原生箭头才能让自定义旋转生效
浏览器默认在 summary 前渲染一个三角形 marker,它和你写的 transform 是两套渲染逻辑——不先干掉它,你的旋转会叠在原生箭头上,甚至被遮挡或错位。
- 最兼容写法:
summary::-webkit-details-marker { display: none; }(覆盖 Chrome/Safari) - 现代标准写法:
summary::marker { content: ""; }(Firefox + Safari 15.4+ 支持) - 别只写
list-style: none,它对summary无效 - 如果用了
::before或::after自定义图标,记得给它也加transform-origin和transition
toggle 事件里改 open 属性不会触发 CSS 旋转动画
用 JS 手动设 details.open = true 确实能展开内容,但 CSS 选择器 details[open] 的匹配是同步的,动画仍会正常触发——这点没问题。真正容易踩坑的是:如果你在 toggle 回调里又去操作 summary.style.transform,就会绕过 CSS 规则,导致动画中断或状态不一致。
- 纯 CSS 控制旋转,就别在 JS 里碰
transform内联样式 - 监听
toggle事件只用于业务逻辑(比如埋点、联动其他组件),不是为了驱动动画 - 确保
details元素没被 JS 设置style.display = 'none'或visibility: hidden,否则offsetHeight计算和动画都会失效
动画卡顿或高度跳变常因 content 重排时机不准
旋转动画本身很轻量,但如果你同时用 max-height 做内容区展开动画,而没处理好重排(reflow)时机,就会看到箭头转完了、内容才“啪”一下弹出来,视觉不同步。
立即学习“前端免费学习笔记(深入)”;
- JS 控制
max-height时,务必在设0后立刻读一次offsetHeight强制重排,再设目标高度 - CSS 里别给
summary设margin-bottom,折叠区内容默认继承它的 margin,容易造成展开时上下跳动 - 字体加载完成前就触发 toggle,
scrollHeight可能低估,导致动画中途截断——可加font-display: swap或延迟初始化
summary 的旋转动画看着简单,但 marker 隐藏、transform 初始值、重排同步这三点漏掉任何一环,都会让效果断在用户眼前。



















