为什么用 transform3d 做移动端动画会卡顿?

诸葛皓宇 阅读 5

我在做移动端的滑动菜单,用了 transform: translate3d(0, 0, 0) 来开启硬件加速,但动画还是有点卡,尤其在低端安卓机上。

我试过加 will-change: transform,也试过只用 translateX,效果都不太理想。是不是我哪里写错了?

这是我的关键 CSS:

.slide-menu {
  transform: translate3d(0, 0, 0);
  transition: transform 0.3s ease-out;
  will-change: transform;
}
我来解答 赞 3 收藏
二维码
手机扫码查看
2 条解答
Tr° 海燕
你这代码本身没啥问题,卡顿大概率是动画元素内部子元素太多,或者动画过程中触发了其他重绘。试试把动画元素单独提出来,给它加个 backface-visibility: hiddenperspective: 1000px 强制走 GPU 合成层。另外检查一下动画过程中有没有其他属性在变,比如 box-shadow 或者 border-radius 这种,它们会让合成层失效,低端机直接炸。如果菜单里有图片,记得给图片加 transform: translateZ(0) 单独提层。
点赞
2026-03-01 23:04
香利 ☘︎
你这个问题我之前也踩过坑,will-change 一直挂在元素上反而会适得其反,尤其是在低端机上,内存压力大得很。

问题出在几个地方:

第一,will-change 不要一直开着,会让浏览器一直给这个元素分配独立的图层,内存消耗大。应该动画开始前加,结束后删掉。

第二,transition 写得太宽泛了,transform 会被解析成所有 transform 相关属性,改成具体值。

第三,检查一下你的滑动菜单里面有没有用 box-shadowborder-radius 这些,它们在动画过程中会导致重绘,直接掉帧。

给你一段改好的代码,复制过去试试:

.slide-menu {
transform: translateX(-100%);
backface-visibility: hidden;
perspective: 1000px;
}

.slide-menu.animating {
will-change: transform;
transition: transform 0.3s ease-out;
}

.slide-menu.open {
transform: translateX(0);
}


const menu = document.querySelector('.slide-menu');

function openMenu() {
menu.classList.add('animating');
menu.classList.add('open');

menu.addEventListener('transitionend', function handler() {
menu.classList.remove('animating');
menu.removeEventListener('transitionend', handler);
});
}

function closeMenu() {
menu.classList.add('animating');
menu.classList.remove('open');

menu.addEventListener('transitionend', function handler() {
menu.classList.remove('animating');
menu.removeEventListener('transitionend', handler);
});
}


还有几个常见的坑要注意一下。菜单里面如果有大量 DOM 节点,或者用了高斯模糊滤镜,低端机基本带不动。实在不行就把 transitionend 换成 requestAnimationFrame 配合 JS 动画库,比如 GSAP,性能会好很多。
点赞 1
2026-03-01 11:02