css(八)浏览器渲染

html-css012

css(八)浏览器渲染,第1张

写css最逃不开的应该是浏览器兼容问题了吧,因为css存在一些 未定义行为 ,各个浏览器都会按照自己的渲染规则来表现,就会存在表现不一致的情况,还有很多属性某些浏览器不支持,很多时候需要我们用更通用的方法来实现一些UI效果。本文重点来说说浏览器是如何把一个页面渲染出来的。

主要流程:

DOM生成、样式计算、布局、分层、图层绘制、栅格化、合成显示

下面主要讲css相关的几个步骤

我们书写的html最终都会被解析成一颗dom树,它来表达的dom结构能被浏览器所理解,那css做的就是赋予dom节点每个元素样式。当然,我们写的css也是不能直接被浏览器理解的,需要转化成styleSheets,我们在浏览器控制台输入document.styleSheets就能看到。

styleSheets要应用到各个元素上还需要两个步骤:

最后得出dom节点每个元素的具体样式。

得到dom树后,浏览器会遍历这棵树,把所有可见的节点加到布局树中,再进行布局计算,得到每个节点的坐标位置,保存在布局树中。

得到每个元素的具体位置后,还不能开始绘制页面,因为我们的页面并不是二维的,3D变换,z轴排序、页面滚动等效果都需要图层来实现。所以浏览器会为特定的节点生成专门的图层便于这些效果的实现。那什么样的节点会创建专门的图层呢,包括拥有层叠上下文属性的元素以及需要剪裁(clip)的地方,可以看一下 css(五)层叠

在浏览器开发者工具会有一个Layers标签,这里面可以直观地看到页面的分层情况

当改变了元素宽高或者几何位置的时候,就会触发 重排 ,需要走一遍完整的渲染过程,开销最大。

如果只是改变颜色,那么布局阶段就不需要执行,可以直接进入绘制阶段,所以叫 重绘 ,省去了布局和分层,效率会比重排要高一些。

而使用css的transform实现动画效果,则可以避开重绘和重排,只进行后续的合成操作,被称为 合成 ,能大大提升绘制效率。

Ps 合成操作实在非主线程(GPU进程)上执行的,不占用主线程资源

使用transform属性的CSS动画看起来比使用left和top属性的动画更平滑。 但是如果你问,“我如何从GPU获得平滑的动画?”在大多数情况下,你会听到像“使用transform:translateZ(0)或will-change:transform这样的建议。著作权归作者所有。 这个问题是因为使用transform和opacity做CSS动画的时候,会将元素提升为一个复合层;而使用js操作css属性做动画时,必须使用translateZ或will-change才能将元素强行提升至一个复合层。 元素本身使用transform和opacity做CSS动画的时候,会提前告诉GPU动画如何开始和结束及所需要的指令;所以会创建一个复合层(渲染层),并把页面所有的复合层发送给GPU;作为图像缓存,然后动画的发生仅仅是复合层间相对移动。 而使用js做动画,js必须在动画的每一帧计算元素的状态;发送给GPU,但不会将元素提升至一个复合层;所以想让元素提升至一个复合层,必须使用translateZ或will-change: transform, opacity。 使用 translate3D 会让浏览器开启硬件加速,性能当然就提高了。translateZ变成3d效果,走GPU渲染。这样也有缺点就是耗电和发热问题。同样的canvas也会开启gpu渲染。CSS3开启GPU硬件加速然后chrome输入chrome://flags/ 能看到这么一句“允许使用 GPU 执行 2D 画布渲染(而非使用软件渲染)”。说明2d是软件渲染的。 参考文献:https://segmentfault.com/q/1010000007962353  https://www.w3cplus.com/animation/gpu-animation-doing-it-right.html  ©  w3cplus.com