css布局优化:布局计算限制— contain/will-change/合成层
Author:zhoulujun Date:
当我们对一个页面进行布局时,性能瓶颈通常是 style、layout、paint。
在《浏览器层面优化前端性能(2):Reader引擎线程与模块分析优化点》提过:
避免大规模、复杂的布局
布局,就是浏览器计算DOM元素的几何信息的过程:元素大小和在页面中的位置。每个元素都有一个显式或隐式的大小信息,决定于其CSS属性的设置、或是元素本身内容的大小、抑或是其父元素的大小。在Blink/WebKit内核的浏览器和IE中,这个过程称为布局。在基于Gecko的浏览器(比如Firefox)中,这个过程称为Reflow。
尽可能避免触发布局
布局的时间消耗主要在于:
需要布局的DOM元素的数量
布局过程的复杂程度
减少绘制区域
有时候尽管把元素提升到了一个单独的渲染层,渲染工作依然是必须的。渲染过程中一个比较有挑战的问题是,浏览器会把两个相邻区域的渲染任务合并在一起进行,这将导致整个屏幕区域都会被绘制。比如,你的页面顶部有一个固定位置的header,而此时屏幕底部有某个区域正在发生绘制的话,整个屏幕都将会被绘制。
注意:在DPI较高的屏幕上,固定定位的元素会自动地被提升到一个它自有的渲染层中。但在DPI较低的设备上却并非如此,因为这个渲染层的提升会使得字体渲染方式由子像素变为灰阶(详细内容请参考:Text Rendering),我们需要手动实现渲染层的提升。
减少绘制区域通常需要对动画效果进行精密设计,以保证各自的绘制区域之间不会有太多重叠,或者想办法避免对页面中某些区域执行动画效果。
简化绘制的复杂度
比如js 获取元素的offsetTop ffsetTop 比如getBoundingClientRect 消耗更少。
在css里面,重绘 backgroun 比如 box-shadow 消耗更好。
优先使用渲染层合并属性、控制层数量
只使用transform/opacity来实现动画效果
应用了transforms/opacity属性的元素必须独占一个渲染层。为了对这个元素创建一个自有的渲染层,你必须提升该元素。在合成层上面的元素,也会合并到此图层中。
用will-change/translateZ属性把动画元素提升到单独的渲染层中
避免滥用渲染层提升:更多的渲染层需要更多的内存和更复杂的管理
过多的渲染层来带的开销而对页面渲染性能产生的影响,甚至远远超过了它在性能改善上带来的好处。由于每个渲染层的纹理都需要上传到GPU处理,因此我们还需要考虑CPU和GPU之间的带宽问题、以及有多大内存供GPU处理这些纹理的问题。
一般情况下,浏览器会把 整个 DOM 作为 CSS 布局上下文,因此:当我们改变部分 DOM 的样式时,也会影响到其他部分。
在布局时,现代主流的浏览器都会做一些智能的判断,最终决定哪些需要改变,哪些不需要改变。不过,页面布局是很复杂的,浏览器不一定能判断到所有的情况。
但是,我们可是使用css contain 属性来限制 回流与重绘
contain
CSS 新出了 contain 属性,拥有 contain 属性(不为 none)的元素与页面其他元素相对独立,并且该元素及其后代元素样式、DOM 发生变化时不会导致整个页面回流和重绘。
contain: none | strict | content | [ size || layout || paint ]
layout:防止元素内 layout 改变影响元素外,也防止其他元素改变影响这个元素。
Any overflow is treated as ink overflow:元素的溢出并不会影响布局,溢出效果类似于 box-shadow、text-decoration
Containing block for absolute positioned、fixed positioned elements:元素后代的定位元素(absolute、fixed)都是相对于元素自身进行定位的
Create stacking context:会创建层叠上下文
No baseline
paint:元素的子元素必须在元素的 content-box 中,溢出内容会被隐藏,效果类似于 overflow:hidden。子元素发生的任何改变都不会影响到与该元素之外的其他元素;同样该元素之外的其他元素都不会影响到子元素
Contents are clipped
Containing block for absolute positioned、fixed positioned elements
Create stacking context
size:在计算元素容器大小时,元素内容会被忽略。用子元素是撑不开这个元素的(声明都不给它的尺寸会一直是 0x0),必须声明尺寸,且子元素不能超出元素的范围,这个属性能够阻止子元素不断变大 -> 改变父元素尺寸 -> 影响更多节点 -> 发成大面积重排。本身提供不了太大性能优化,一般是和 layout 搭配使用。
Treated as having no contents
style:有些 CSS 属性会影响不只宿主元素和其子元素,比如 counter。为了限制这样的属性影响到别的元素,让它的影响力限制在宿主元素和其子元素范围内。强行生成一棵 DOM 子树,变成像 shadow dom 那样的情况,外面的变量不会影响里面的;里面的也不会影响到外面。
counters and quotes cannot escape this element
contain: style 存在风险,暂为将其放入规范中
content:同时包含 content、paint、style的效果
strict:同时包含 layout、content、paint、style的效果
适用场景
元素在屏幕外不可见时
第三方插件
container queries
contain容易混淆的就是, background-size属性的值:cover和contain的缩放背景图
background的cover和contain
contain,按比例调整背景图片,使得其图片宽高比自适应整个元素的背景区域的宽高比,因此假如指定的图片尺寸过大,而背景区域的整体宽高不能恰好包含背景图片的话,那么其背景某些区域可能会有空白。
cover,按比例调整背景图片,这个属性值跟contain正好相反,背景图片会按照比如自适应铺满整个背景区域。假如背景区域不足以包含背景图片的话,那么背景图片就会被咔嚓。
contain | 此时会保持图像的纵横比并将图像缩放成将适合背景定位区域的最大大小。 等比例缩放图象到垂直或者水平其中一项填满区域。 |
cover | 此时会保持图像的纵横比并将图像缩放成将完全覆盖背景定位区域的最小大小。 等比例缩放图象到垂直和水平两项均填满区域。 |
display:contents
display:contents 使 div 不产生任何框 ,因此不会渲染其背景 边框 和 内边距 ,但颜色 / 字体等继承的属性还是会对其子元素产生效果
即在盒子上添加 display : contents , 当前盒子若设置了 background border padding width height 等属性会失效
参考文章:
介绍 contain 属性 https://www.hexuanzhang.com/2822848773.html
听说有个能优化性能的属性 contain https://zhuanlan.zhihu.com/p/30618818
https://www.CSS性能优化新属性 contain 的语法、作用及使用场景 webhek.com/post/css-contain-property.html
http://www.cnblogs.com/freefish12/p/5776747.html
转载本站文章《css布局优化:布局计算限制— contain/will-change/合成层》,
请注明出处:https://www.zhoulujun.cn/html/webfront/style/cssBase/2020_0813_8543.html