transition必须写在真正要动的元素上,而非触发器;需精确匹配变化属性(如transform),避免all;初始态须显式定义(如translateX(0));translate值必须为可插值的具体数值;慎用百分比和top/left混用;移动端卡顿常因未启用GPU合成或重绘触发;transitionend监听前需确认动画实际执行。

transition必须写在要动的元素上,不是触发器上
很多人把transition: transform 0.3s写在:hover的父元素或按钮上,结果位移没动画——因为真正要动的元素自己没声明过渡。比如悬停按钮时让弹层滑入,transition得加在弹层元素自身,而不是按钮上。
常见错误写法:.trigger:hover .panel { transform: translateX(200px); },但.panel没配transition,位移就是瞬移。
-
transition必须和变化属性精确匹配:改transform就写transition: transform 0.3s - 避免用
transition: all 0.3s,它会让width、color等意外参与动画,引发重绘 - 初始态必须显式定义,比如
transform: translateX(0),不能依赖浏览器默认值
translate值必须可动画,且起点终点都得是具体数值
translate()本身支持动画,但前提是起始和目标值都是明确的、可插值的长度单位(px、em、%等)。如果其中一个是unset、initial或空值,动画不会启动。
例如:.box { transform: translateX(0); } → .box.active { transform: translateX(100px); } 可动;但.box { transform: none; } → .active { transform: translateX(100px); } 就不动。
立即学习“前端免费学习笔记(深入)”;
- 推荐统一用
translateX()/translateY(),语义清晰,避免translate(100px, 0)里隐式Y轴值干扰 - 百分比值要注意:
translateX(50%)是相对于自身宽度,不是父容器,容易误判位移距离 - 不要混用
top/left和translate,否则会覆盖或冲突,导致动画失效或跳变
移动端卡顿?检查是否触发了重排或合成层丢失
理论上transform: translate()走GPU合成层,不该卡。但实际中常因几个细节掉回主线程渲染:
- 漏加
will-change: transform或transform: translateZ(0),尤其在低端安卓WebView里,动画可能撕裂或掉帧 - 父容器有
overflow: hidden且子元素位移超出边界,部分Android版本会强制重绘整个区域 - 元素带复杂背景(渐变、滤镜)、阴影或抗锯齿字体,会破坏图层合并,导致绿色“paint flashing”块大面积闪烁
- 动画元素太多(>6个同时运行),GPU内存吃紧,建议控制并发动画数量
transitionend事件监听不到?先确认动画真正在执行
很多开发者绑了transitionend却收不到回调,根本原因往往是动画压根没跑起来:
- 用
getComputedStyle(el).transform打印当前值,确认初始态和目标态确实不同 - 别在class切换后立刻监听:DOM更新是异步的,应加
setTimeout(() => el.addEventListener('transitionend', handler), 0) - 多个过渡属性(如
transform和opacity)会触发多次事件,需过滤:if (e.propertyName === 'transform') - JS直接赋值
el.style.transform = 'translateX(100px)'前,必须确保该元素已声明transition,否则事件不触发
最隐蔽的坑是:动画元素被display: none隐藏过,再show出来时transform状态未重置,导致transition无法从“有值”变到“新值”。


















