更新(2016年)。关于这项技术的更经典的文章是在《高性能动画--HTML5摇滚》。TL;DR: 只有transform &opacity; 没有top/left!
在现代,我们有两个主要的选择,可以在屏幕上移动一个元素。
- 使用CSS 2D变换和
translate() - 使用
position:absolute和top/left
有人问Chris Coyier为什么要使用translate。请阅读他的回答,其中很好地涵盖了为什么为设计目的移动元素(使用transform )与你的元素布局无关(使用position )更符合逻辑。
我想用Chrome浏览器来回答这个问题,并获得一些关于发生了什么的好证据。最后我录制了一个关于这个经验的视频。
这段视频很好看,它深入探讨了Chrome DevTools的时间线、合成、绘画成本、加速图层等等......但如果你想看简略的文字版本,请继续阅读。
第一件事,克里斯做了一些简单的演示,以尝试一些东西。
这有点作用,但在这种情况下,复杂度很低,都会看起来很不错。我们需要一些更接近于复杂网站的东西来正确评估这两者*(感谢joshua*提供的Macbook!)。
现在我们开始接近了,但我马上就被一些东西分散了注意力。
分心。像素抢购
如果你运行上面的演示,你可能会注意到MacBook的顶部边缘在顶部/左侧看起来好一点。(我在这里写了一篇关于为什么翻译更好的文章!荒谬!)所以这是由于绝对定位的Macbook坚持像素的位置,而translate()'d可以在亚像素位置插值。
Chrome浏览器的一位GPU工程师James Robinson称这为 "dubstep效应",因为这些像素似乎正在受到低音的冲击。下面是这种效果的特写......观察每张照片中Macbook的顶部白边。

在左边,你看到阶梯式下降了三个像素,然后又重新上升。在这种情况下,这种像素捕捉可能会导致较少的分心过渡,尽管如果你是在高对比度较低的情况下移动物体,这就不会那么明显了。
回到性能问题
如果你在这两个例子上运行DevTool的时间线框架模式,它们开始讲述一个非常不同的故事。

顶部/左边的每一帧都有非常大的时间来绘制,这导致了更多的过渡。所有的CSS,包括一些大的盒状阴影,都是在CPU上计算的,并且每一帧都是在渐变的背景下合成的。另一方面,translate ,将笔记本元素提升到GPU上自己的层(称为RenderLayer)。现在,它位于自己的层上,任何2D转换、3D转换或不透明度的变化都可以完全发生在GPU上,这将保持极快的速度,并且仍然可以让我们获得快速的帧率。
请看上面的视频的最后部分,以了解更多关于如何诊断绘画成本,查看哪些区域正在被重新绘画,以及评估哪些元素在GPU上。
演示
点击下面的视频,尝试添加更多的内容,看看帧率是如何反应的。也可以随意打开DevTools,探索时间轴。
动画的准则
- 如果可能的话,使用CSS关键帧动画或CSS过渡。浏览器可以在这里对绘画和合成进行大量优化。
- 如果需要它是基于JS的动画,使用
requestAnimationFrame。 避免使用setTimeout、setInterval。 - 如果可以的话,避免在每一帧上改变内联样式(jQuery
animate()-style),CSS中的声明式动画可以被浏览器优化的更多。 - 使用2D变换而不是绝对定位,通常会通过更小的绘制时间和更平滑的动画来提供更好的FPS。
- 使用时间轴框架的模式来调查是什么拖累了你的行为
- "显示绘制矩形 "和 "渲染合成层边框 "是验证你的元素正在被渲染的好办法。





