浏览器的渲染流程分为三步:布局(Layout)、绘制(Paint)、混合(Composite)。
当浏览器计算出哪条款式是作用在哪个元素身上当前,就须要将款式转换成 px 并显示在屏幕上。这个过程就是渲染(rendering),整个过程能够分为三步:布局,绘制,混合。
布局
渲染的第一步是布局,浏览器计算每个元素要在文档中占据的空间。因为有默认的文档流,元素的大小和地位会影响到页面中其余元素的大小和地位。布局就是将他们计算出来。
任何时候扭转一个元素的宽高或者调整它的定位偏移值(Left / top 等),浏览器就会从新计算这个元素的布局。同样的,如果插入一个元素到文档流中,或者通过 JS 从文档流中移除一个元素,浏览器也会从新计算该元素的布局。当一个元素的布局产生扭转,浏览器必须从新计算其余被该元素所影响的元素的布局,这个过程称为「回流」。
绘制
布局后,就是绘制了。绘制就是将布局还原成 px:文本、图片、边框和暗影等。这个过程可能不会显示在屏幕上,而是绘制到内存中。页面中的某些局部将会绘制为「层」。
假如扭转某个元素的背景色彩,浏览器就会从新绘制这个元素。然而,因为背景色彩不会对页面中其余元素的大小或者地位造成影响,浏览器不须要从新计算布局;绝对来对,批改元素的大小比批改背景色彩更加消耗计算资源。
失常状况下,页面中的元素能够被提取到一个本人的「层」。浏览器会别离绘制页面中的每个「层」,浏览器会将这些「层」发送给计算机的 GPU(Graphics processing unit)渲染,而不是和页面中的「主层」一样通过 CPU 来解决。通过 GPU 渲染可能放慢处理速度,因为 GPU 有做最优化解决。
通常这被称之为 硬件加速(Hardwar acceleration),因为它依赖于计算机的硬件去为它提供渲染减速。更多的「层」意味着更多的资源耗费,然而他可能放慢页面的渲染速度。
混合
混合就是浏览器绘制出所有的「层」,造成最初的图像,并且展现到页面上。各个「层」将会以特定的顺序排列,为的是在有元素产生笼罩的中央,各层级之间可能正确的显示。
当更改 opacity 或者是 transform 属性时,渲染工夫比更改其余属性要快很多。因为浏览器会将这些元素晋升到一个特定的「层」并且应用 GPU 减速渲染。因为元素位于它本人所处的「层」,所以在 opacity 或者是 transform 变换的过程中,它不会对「主层」造成影响或反复绘制。
在对页面进行小改变时,GPU 的最优化通常不会有影响。然而如果对动画成果做出扭转,屏幕就须要在一秒内更新几十次;在这种状况下,渲染速度就成问题了。大部分的屏幕一秒钟刷新 60 次(60 HZ),所以现实状况下,如果要使动画在屏幕上尽可能晦涩的显示,对动画做出的扭转起码也会被计算这么屡次。浏览器每次计算的工作越多,渲染的速度就越慢。
应用 will-change 属性管制「层」
浏览器已就优化渲染流程致力了很久,为的是将元素尽可能地拆散成独自的「层」。如果动画成果来自 opacity 或 transform 属性,在古代浏览器中,为了使动画可能晦涩的显示,通常会依据各种条件,例如系统资源,来做出一个比拟好的决定。然而偶然会遇到闪动等问题。如果你碰到过这种状况,你能够应用 will-change 属性来管制渲染中的「层」。这个属性会提前通知浏览器筹备承受须要扭转的特定的属性。浏览器就会把这个元素晋升到独自的「层」来渲染。例如:
will-change: transform
代表你将要扭转这个元素的 transform 属性。然而,尽量不要应用这个属性,除非你遇到过以上问题,因为它会应用更多的系统资源。最好是在发现它使动画的渲染变得更加晦涩的状况下才应用。更进一步的理解此属性,查看这篇文章
值得注意的是自从这篇文章公布当前有些事件在悄悄发生变化,以前只有 3D 转换才会晋升为本人的「层」,然而当初古代浏览器曾经反对通过 GPU 减速为 2D 提供本人的「层」了。
当咱们在应用动画的时候,最好是应用 transform 或者 opacity。而后才思考应用可能会引起「重绘」的属性,不要不得已不要应用会引起从新布局的属性来设置动画,如果应用了,就要当心是否造成了性能问题。如果你想晓得哪些属性会影响布局、绘制和混合,看这里。
参考:
《CSS in Depth》by Keith J. Grant