移动端css动画卡顿90%因使用top/left/width/height等触发重排的属性;唯有transform和opacity可稳住60fps,因其走gpu合成线程,不触发重排重绘,且@keyframes和transition中须严格仅含这两类属性,混入其他属性或js读取布局信息均会导致降级。

移动端 CSS 动画卡顿,90% 是因为用了 top、left、width、height 这类属性——它们一动就触发重排,低端安卓机(尤其是 Android 5–7 WebView)直接掉到 20fps。真正能稳住 60fps 的,只有 transform 和 opacity。
为什么 top/left 动画必卡
每次改 top 或 left,浏览器都得重新计算整个文档流的位置、尺寸、换行……这个过程叫重排(reflow),全靠 CPU 干活。低端安卓机调度弱,一帧内反复重排,主线程瞬间堵死,手指滑动都“粘滞”。而 transform: translateX(100px) 只走合成线程,GPU 直接挪图层,不碰布局也不重绘。
- 错:
transition: left 0.3s→ 整条过渡降级回 CPU 渲染 - 对:
transition: transform 0.3s→ 且只改transform,别混top或margin - 动画中哪怕偷偷读一次
getBoundingClientRect(),也会立刻退回到重排流程
@keyframes 里只留 transform 和 opacity
关键帧动画里塞进一个非合成属性,整段动画就废了。浏览器不会报错,但帧率会默默掉下去。
- 安全组合:
@keyframes slide { from { transform: translateX(-100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } - 危险操作:加
box-shadow、filter、background-color→ 可能破坏图层合并,引发重绘 - 缩放别碰
width/height,用transform: scale(0.9);旋转用rotate(45deg),不是margin-left模拟
will-change 不是保险丝,是定时器
静态写 .item { will-change: transform; } 等于给每个元素提前建 GPU 图层,内存吃紧时安卓低端机直接 OOM 卡死。
- 正确时机:动画开始前 1–2 帧用 JS 设置
el.style.willChange = 'transform' - 必须清除:监听
transitionend后立刻设el.style.willChange = 'auto' - iOS Safari 对 ≤16ms 动画可能不触发事件,加兜底:
setTimeout(() => el.style.willChange = 'auto', duration + 100) - 绝对不要对列表项批量加,比如
.list-item { will-change: transform; }
怎么确认 GPU 加速真生效了
写了 transform 不等于就加速了。得看浏览器是否真建了独立图层。
- Chrome DevTools → Rendering 面板 → 勾选 “Layer Borders”:有绿色边框才是合成层
- 没绿框?检查父容器是否设了
overflow: hidden或filter: blur(1px)—— 这些会抑制子元素提层 - 动画中改
opacity却没绿框?可能是父级transform: none抑制了图层提升
最常被忽略的点,是以为加了 transform 就万事大吉,结果在动画回调里顺手读了 offsetWidth,或者 class 切换时多改了一个 background-color —— 这种“混合属性”操作,会让整条渲染路径悄悄退回 CPU。真正顺滑的前提,是整条路径只走合成阶段,一步都不能偏。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











