transition仅适用于状态切换类简单动画,如显隐、位移、缩放、透明度变化;不能替代需中间帧控制、时间轴调度或运行时计算的JS动画。

transition 能替代哪些 JS 动画逻辑
只有「状态切换」类的简单动画适合用 transition 替代,比如显隐、位移、缩放、透明度变化。它不能替代需要中间帧控制、时间轴调度(如 requestAnimationFrame)、或依赖 JS 运行时计算的动画(比如滚动视差、物理模拟)。如果你的回调里只是 element.style.left = x + 'px' 然后递增,那基本可以平替;但凡有 setTimeout 嵌套、条件分支跳帧、或要监听动画结束再触发下一步,就得留 JS 控制层。
怎么写 transition 才不卡顿、不闪一下
常见错误是只加 transition: all 0.3s,结果字体模糊、背景重绘、甚至触发强制同步布局。关键在「精准声明要过渡的属性」和「启用硬件加速」:
- 用具体属性代替
all,比如transition: opacity 0.2s, transform 0.2s -
transform和opacity是仅有的两个能走合成层(compositor)的属性,不会触发重排(reflow) - 避免对
width、height、top/left等触发布局的属性做过渡 - 必要时给元素加
will-change: transform(但别滥用,会提前占用 GPU 内存)
JS 触发 transition 的正确姿势
直接改 class 或 style 后立刻读取 offsetTop/offsetHeight,会导致浏览器强制同步计算样式,打断过渡流程,造成首帧卡顿或跳变。必须让浏览器先完成样式计算,再触发过渡:
- 用
element.classList.add('active')切换 class,不要 inline 改style - 如果必须 JS 控制,用
setTimeout(() => { element.style.transform = 'translateX(100px)' }, 0)或Promise.resolve().then(...)微任务延迟 - 监听
transitionend事件时注意:多个属性过渡会触发多次,需检查event.propertyName === 'transform'
兼容性与 fallback 怎么处理
IE10+ 支持 transition,但不支持 transition: transform 的简写写法(得写全 -webkit-transform),更老的 Android WebView 可能忽略 will-change。真正麻烦的是「过渡失败时 JS 回调还在跑」:
立即学习“前端免费学习笔记(深入)”;
- 用
getComputedStyle(element).transitionProperty检测是否支持(但注意返回值可能是none或空字符串) - 不要依赖
transitionend做核心逻辑,比如移除 DOM —— 加个超时兜底:setTimeout(() => cleanup(), 300 + 50) - 动画属性值必须有明确初始态和终态,比如
opacity从1→0,不能从unset→0,否则过渡不生效
最易被忽略的是:CSS 过渡没有「取消」机制。JS 动画可以随时 cancel(),而 transition 中途改值只会重新开始,不是中断续播。如果业务里存在频繁交互中断动画的场景(比如 hover 进出太快),得靠 JS 记录状态 + 强制重置 class 来绕过。










