transition必须写在要动的元素上,而非触发器;需精确匹配transform属性,避免all;初始态须显式定义如translatex(0);禁用top/left以防重排;移动端应加translatez(0)提升gpu合成兼容性。

transition 必须写在要动的元素上,不是触发器上
很多人把 transition: transform 0.3s 写在父容器或按钮上,结果 hover 时子元素位移毫无动画——因为真正要动的元素没声明过渡属性。浏览器只对「自身样式变化」做插值,不跨元素推导。
常见场景:.card:hover .badge 要上浮,transition 得加在 .badge 选择器里,而不是 .card 或 :hover 伪类本身。
- 错误写法:
.card:hover { transition: transform 0.3s; }(无效) - 正确写法:
.badge { transition: transform 0.3s ease; }+.card:hover .badge { transform: translateY(-8px); } - 如果用 JS 动态设置
el.style.transform,也要提前在 CSS 里写好transition,否则 JS 设置后不会自动补上
只对 transform 做 transition,别碰 top/left
top 和 left 触发重排(reflow),哪怕加了 transition,滚动或高频率交互时也容易卡顿;transform: translate() 走合成层,GPU 加速,性能稳定。
即使你用的是 position: absolute,也应保持 position 不变,只改 transform。
- 避免混用:
top: 20px; transform: translateX(10px)会强制回退到主线程渲染 - 移动端兼容性补丁:加
transform: translateZ(0)或will-change: transform(仅 hover 时设,别常驻) - 初始值必须明确:
transform: translateX(0)不能省略成unset或留空,否则从“无”到“有”不触发动画
为什么 hover 进入有动画、退出却瞬移?
根本原因是写了 transition: all 0.3s 或漏写了某些状态的初始值。浏览器发现某个属性在 hover 态有值、常态没定义(比如 opacity 或 z-index),就会在退出时跳变。
更隐蔽的问题是:父元素 overflow: hidden + 子元素 transform 移出边界,退出时因裁剪重绘导致视觉“闪回”。
- 永远用显式配对:
.el { transform: translateY(0); transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); } - 慎用
all:它会让color、font-size等意外参与过渡,调试困难 - 检查 computed style:用
getComputedStyle(el).transform确认常态和 hover 态的值是否真不同
transitionend 监听不到?先确认它有没有真正跑起来
transitionend 只在动画帧真正执行完才触发。很多情况下它压根没启动——比如目标 transform 和当前值一样,或者被更高优先级样式覆盖。
JS 动态设置时尤其容易踩坑:class 切换后立刻监听,但浏览器还没完成样式计算。
- 安全监听写法:
setTimeout(() => el.addEventListener('transitionend', handler), 0) - 过滤多属性动画:
if (e.propertyName === 'transform') { ... } - 调试技巧:Chrome DevTools → Rendering → 勾选 “Paint flashing”,看绿色块是否只覆盖元素本体;若整行/整块闪,说明
transform没生效,可能被top/left或margin干扰
position,只动 transform,所有过渡写在常态选择器里,hover 或 class 切换只负责改值。复杂交互动画建议交给 @keyframes 或 GSAP,CSS transition 适合明确起止点的轻量位移。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











