为什么我的CSS动画在Chrome渲染面板显示大量重排但实际很卡?
我在用Chrome DevTools的Rendering面板调试一个CSS动画,发现Layers里显示有很多蓝色的Layout区域,但实际动画在60帧时偶尔还是会卡顿。我用的是transform和opacity组合动画:
@keyframes move {
50% { transform: translateX(200px); }
100% { opacity: 0; }
}
.box {
width: 100px;
animation: move 2s infinite;
}
按说transform应该走合成层,可为什么渲染面板显示这么多布局重排?我试过把opacity改成transform的矩阵变换,卡顿确实缓解了,但这样写太麻烦了。有没有更好的解决办法?
transform: translateX(200px)本身虽然不会触发重排,但**如果动画元素影响了文档流或其他元素的布局(比如后续元素依赖它的位置)**,就会导致浏览器仍然进行Layout计算。解决方案很简单:**让动画元素脱离文档流**,这样就不会影响其他元素布局了。加个
position: absolute就行了:这样Chrome就不会为这个动画频繁重排布局了。卡顿问题基本也就解决了。
opacity这个属性会触发重排(reflow),虽然你用的是transform,但opacity还是会拉低性能。Chrome渲染面板显示的蓝色区域就是布局重排的地方。解决办法很简单,你可以把
opacity换成filter: opacity(0),这样就不会触发重排了,因为filter是GPU加速的属性。代码改一下就行:不过要注意一点,
filter在一些老版本浏览器可能不支持,所以如果需要兼容IE之类的,还是得做个降级方案或者提醒用户。另外,确保你的动画元素是独立层(composited layer),可以用
will-change: transform, opacity;来提前告知浏览器你要做这些动画,减少不必要的计算开销。但别滥用will-change,否则也会增加内存消耗。最后提醒一句,调试时注意看看有没有其他地方也在频繁触发重排,有时候卡顿可能是别的代码引起的,排查要全面点。