为什么我的CSS动画在低端手机上卡顿严重?

公孙怡彤 阅读 36

我用 transformopacity 做了一个简单的入场动画,但在一些老款安卓机上特别卡,掉帧很明显。明明查资料说这两个属性不会触发重排,应该性能不错才对啊。

这是我的关键代码:

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.item {
  animation: fadeInUp 0.6s ease-out;
}

是不是还漏了什么优化点?比如要不要加 will-change 或者开启硬件加速?

我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
UI芳宁
UI芳宁 Lv1
你用的 transform 和 opacity 确实是官方文档里推荐的动画属性,不触发重排这点没问题。但低端机卡顿通常不是动画属性本身的问题,而是合成层(Compositing Layer)没处理好。

先说 will-change 这东西,别滥用。它确实能让浏览器提前为元素创建独立的合成层,但你在低端机上用反而可能增加内存负担。正确的用法是只在动画开始前瞬间添加,动画结束后移除,像这样:

.item {
will-change: transform, opacity;
/* 动画结束后移除这个属性,让浏览器释放资源 */
}

.item.animation-done {
will-change: auto;
}


更直接的做法是用 transform: translate3d(0, 0, 0) 或者 transform: translateZ(0) 强制把元素拉到独立的合成层,这个比 will-change 更可控:

@keyframes fadeInUp {
from {
opacity: 0;
transform: translate3d(0, 20px, 0);
}
to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}


另外检查一下你的动画元素有没有放在 overflow: hidden 的容器里,如果有的话,容器本身可能也会影响合成层的提升。

如果上面这些都试了还是卡,有个比较极端的做法是把动画改成 animation-fill-mode: forwards 然后在动画结束后直接用 class 切换到最终状态,把动画层拿掉。不过这个要看具体场景,不是所有交互都适合。

最后提醒一句,老款安卓机的 GPU 本来就弱,如果动画元素特别多(比如列表项),就是再优化也扛不住,那种情况考虑用 IntersectionObserver 做懒加载,分批执行动画。
点赞
2026-03-17 22:02