Android 5–7 WebView 动画必须仅用 transform 和 opacity,因 top/left 触发重排致卡顿;需避免混用非合成属性、慎用 will-change、禁读布局信息,确保全程合成渲染。

只用 transform 和 opacity 做动画,其他属性全砍掉——这不是优化建议,而是 Android 5–7 WebView 能稳住 60fps 的底线。
为什么 top/left 一动就卡成幻灯片
改 top 或 left 会强制触发重排(reflow),浏览器得在主线程里重新算位置、尺寸、换行、文本流……低端安卓机 CPU 调度弱,一帧内卡住多次,动画直接断帧。实测在 MT6737(Android 6.0)上,top: 20px 动画帧率常跌破 20fps。
-
top: 20px; left: 30px;→ 改为transform: translate(30px, 20px); - 需要更强 GPU 提示时,用
transform: translate3d(30px, 20px, 0);,比translateZ(0)更明确 - 绝对不要混写:
transform: translateX(100px); top: 50px;—— 后者会让浏览器放弃图层优化
@keyframes 和 transition 里只留安全属性
混进一个非合成属性,整条动画流水线就降级回 CPU 渲染。浏览器不会报错,但帧率会默默掉下去。
- 错:
transition: left 0.3s, opacity 0.3s→left拖垮全部 - 对:
transition: transform 0.3s, opacity 0.3s -
@keyframes中删掉所有width、height、margin、box-shadow、filter、border-radius(尤其配合transform时) - 关键帧尽量压缩:从
0% → 25% → 50% → 75% → 100%简化为0% → 100%,用cubic-bezier(0.34, 1.56, 0.64, 1)替代ease-in-out
will-change 是定时器,不是开关
静态写死 will-change: transform 在 CSS 里,等于让浏览器永远给这个元素建独立图层——内存涨、上下文切换多,安卓低端机反而 OOM 卡死。
立即学习“前端免费学习笔记(深入)”;
- 加的时机:用户交互触发瞬间(如
touchstart),或requestAnimationFrame第一帧内 - 删的时机:监听
animationend或transitionend后立刻执行el.style.willChange = 'auto' - iOS Safari 对 ≤16ms 的动画可能不触发
animationend,务必加兜底:setTimeout(() => el.style.willChange = 'auto', duration + 100) - 别对列表项批量设:
.list-item { will-change: transform; }—— 安卓低端机容易图层爆炸
别让 JS 在动画中偷偷读取布局信息
这是最常被忽略的掉帧元凶。哪怕只是调一次 getBoundingClientRect()、offsetHeight 或写 style.width,也会强制同步 layout,直接破防。
- 动画过程中禁用所有
offsetTop、clientWidth、getComputedStyle()(除非你明确知道它不触发 layout) - 如果必须读取,把读操作提前到动画开始前,或延后到
animationend之后 - 用 Chrome DevTools 的 Rendering → Paint flashing 看绿色是否集中在阴影/文字区域;Layers 面板确认目标元素是否真生成了绿框图层
真正顺滑的前提,不是“用了什么酷炫技巧”,而是整条渲染路径从头到尾只走合成阶段——任何一次意外的 layout 或 paint,都会让低端安卓机当场缴械。


















