改top/left必卡帧,因其触发cpu密集型重排(reflow),需重算文档流布局;而transform仅由gpu合成线程处理,不阻塞主线程,是守住60fps的唯一可靠方案。

为什么改 top 或 left 就卡帧
每次修改 top 或 left,浏览器必须重新计算整个文档流的位置、尺寸、换行、文本布局——这个过程叫重排(reflow),完全依赖 CPU。低端安卓机(尤其是 Android 5–7 WebView)调度能力弱,一帧内反复重排,主线程瞬间堵死,滑动都“粘滞”。transform: translateX(100px) 则只挪图层,由 GPU 合成线程处理,不碰布局也不重绘。
@keyframes 里混进一个 margin 就全段降级
浏览器不会报错,但只要关键帧中出现任意一个触发重排或重绘的属性,整段动画就默默退回到 CPU 渲染模式。常见高危写法包括:
-
background-color动画 → 触发重绘,像素级压力大 -
box-shadow动画 → 阴影值变化反复创建/销毁合成层 -
filter: blur()→ CPU 做高斯模糊,blur(1px)就可能拖垮帧率 -
width/height→ 改变盒模型尺寸,影响后续所有元素流式布局
安全写法只保留:transform 和 opacity。
will-change 不是加速开关,是内存定时器
will-change: transform 是提示,不是指令;浏览器是否建层、何时回收,由实现决定,不可控。静态写 .item { will-change: transform; } 等于给一屏 20 个列表项各占一块 GPU 内存,低端安卓极易 OOM 卡死。
正确用法:
- 仅在用户真实交互瞬间动态添加:
el.style.willChange = 'transform, opacity' - 动画结束后立刻清除:
el.addEventListener('animationend', () => el.style.willChange = 'auto') - iOS Safari 可能丢事件,加兜底:
setTimeout(() => el.style.willChange = 'auto', duration + 100)
移动端掉帧往往不是没开 GPU 加速,而是你根本没意识到自己正用 left 把浏览器拖进泥潭
真正能守住 60fps 的底线,只有 transform 和 opacity。其他所谓“视觉变化”类属性,比如 color、background-color、box-shadow,哪怕只出现在一帧里,也会让整段动画失去 GPU 合成资格。最常被忽略的细节是:动画卡顿从来不是因为效果不够炫,而是因为你在 @keyframes 里悄悄加了一行 margin: 0,或者用 jQuery.animate() 默认改了 top。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











