只用 transform 和 opacity 做动画是低端安卓机(android 5–7 webview)维持 60fps 的底线,因其走合成线程不触发重排重绘;其他属性如 top/left/width/height/color/background-color 会引发主线程阻塞,导致帧率骤降。

直接结论:只用 transform 和 opacity 做动画,其他属性全砍掉——这不是优化建议,而是低端安卓机(尤其 Android 5–7 WebView)能跑满 60fps 的底线。
为什么 top/left/width/height 一动就卡
这些属性改了会触发重排(reflow),浏览器得重新计算整个文档流位置、尺寸、换行……主线程瞬间堵死。低端安卓机 CPU 调度弱,一帧内反复重排,帧率直接掉到 20fps 以下,手指滑动都感觉“粘滞”。transform 和 opacity 则不同:它们只走合成线程(compositor thread),GPU 直接处理图层位移和透明度混合,不碰布局和绘制。
- 位移动画必须写成
transform: translateX(100px),不是left: 100px或margin-left: 100px - 缩放统一用
transform: scale(0.9),别碰width/height - 文字颜色渐变别用
color动画,改用两层文字叠在一起,靠opacity切换显隐来模拟 - 哪怕只是
background-color过渡,也比opacity更耗资源——它属于重绘(repaint),而opacity是纯合成
transition 和 @keyframes 里只留安全属性
过渡或关键帧里混进一个非合成属性,整条动画流水线就会降级回 CPU 渲染。浏览器不会警告你,但帧率会默默掉下去。
- 错:
transition: left 0.3s, opacity 0.3s→left拖垮全部 - 对:
transition: transform 0.3s, opacity 0.3s - @keyframes 中只写
transform和opacity,删掉所有box-shadow、filter、width、top - 动画时长控制在 200–300ms,太短没反馈感,太长让低端机更难稳住帧率
will-change 不是加速器,是双刃剑
在低端安卓机上,will-change: transform 写死在 CSS 里等于提前给每个元素建 GPU 图层,内存吃紧时反而 OOM 卡死。它只在真正要动的那一刻才该出现。
- 动画开始前 1–2 帧用 JS 设置:
el.style.willChange = 'transform' - 监听
transitionend或animationend后立刻清空:el.style.willChange = 'auto' - iOS Safari 对 ≤16ms 的动画可能不触发
animationend,加兜底:setTimeout(() => el.style.willChange = 'auto', duration + 100) - 绝对不要写
.list-item { will-change: transform; }—— 列表滚动时批量创建图层,安卓低端机直接卡住
别让 JS 在动画中偷偷读取布局信息
这是最常被忽略的掉帧元凶。哪怕你 transform 写得再干净,只要动画过程中 JS 调用了 getBoundingClientRect()、offsetTop 或 clientWidth,浏览器就得立刻同步执行重排,整条合成流水线崩盘。
- 动画期间禁止任何 layout-triggering 的读操作
- 如果必须读取,把读操作集中到
requestAnimationFrame开头,写操作放到结尾,避免强制同步 - 检查第三方库(比如轮播组件、下拉刷新)是否在动画中偷偷读取尺寸——它们往往比你自己写的代码更危险
真正顺滑的前提,不是“用了 transform”,而是整条渲染路径从头到尾只走合成阶段。任何一次意外的重排或重绘,都会让低端安卓机的帧率断崖式下跌。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











