新的CSS特性contain控制页面重绘和重排
时间:2023-03-30 18:40:09
CSS
在介绍新的CSS属性contain之前,读者首先需要了解什么是页面重绘和重排。之前已经介绍过很多次了,如果不太了解的话,可以看看这个提高CSS动画性能的正确姿势。OK,让我们进入本文的正题,什么是contain?contain属性允许我们指定特定的DOM元素及其子元素,使它们独立于整个DOM树结构。目的是使浏览器能够只重绘和重新排列某些元素,而不必每次都以整个页面为目标。contain属性允许作者指示元素及其内容尽可能独立于文档树的其余部分。这允许浏览器为DOM的有限区域而不是整个页面重新计算布局、样式、绘画、大小或它们的任意组合。contain语法查看其语法:{/*无布局包含。*/包含:无;/*为元素打开大小限制。*/包含:大小;/*打开元素的布局包含。*/包含:布局;/*打开元素的样式包含。*/包含:样式;/*为一个元素打开paintcontainment。*/包含:油漆;关于布局、油漆和尺寸的遏制。*/包含:严格;/*为布局和绘制打开包含。*/contain:content;}除了none,还有6个值,我们一一来看。contain:sizecontain:size:设置了contain:size的元素的渲染不会受到其子元素内容的影响。该值打开元素的尺寸限制。这确保了可以在不需要检查其后代的情况下布置包含框。开始看到这个定义也是一头雾水,光看定义很难理解是什么意思。还需要练习:假设我们有如下简单的结构:
.container{width:300px;填充:10px;border:1pxsolidred;}p{border:1pxsolid#333;边距:5px;font-size:14px;}并且,在jQuery的帮助下,每次单击容器时添加一个
Coco
结构:$('.container').on('click',e=>{$('.container').append('
Coco
')})然后会得到如下结果:可以看到container.container的高度会随着元素的增加而增加,这是正常的。这时我们在容器.container中添加一个contain:size,上面说到:设置了contain:size的元素的渲染不会受到其子元素内容的影响。.container{宽度:300px;填充:10px;border:1pxsolidred;+contain:size}看看会发生什么:正常情况下,父元素的高度会因为子元素的增加而升高,但是现在,子元素的变化不再影响样式布局父元素的作用,也就是contain:size的作用。contain:style接下来说一下contain:style、contain:layout和contain:paint。先看看contain:样式。在撰写本文时,contain:样式已被暂时删除。CSSContainmentModuleLevel1:从本规范中删除有风险的“样式包含”功能,将其移至Level2。好吧,官方的说法是由于某些风险而暂时将其删除。在规范的第二版中可能会重新定义,所以暂时搁置该属性。contain:paintcontain:paint:一个带有contain:paint的元素设置了布局约束,意思是通知UserAgent这个元素的子元素不会显示在这个元素的边界之外。因此,如果元素在屏幕外或以其他方式设置为不可见,它也保证其后代不可见且不被渲染。该值打开元素的绘制包含。这确保了包含框的后代不会显示在其边界之外,因此如果一个元素在屏幕外或以其他方式不可见,它的后代也保证不可见。这个稍微好理解一点。先来看第一个特点:设置了contain:paint的元素的子元素不会显示在这个元素的边界之外。设置了contain:paint的元素的子元素将不会在这个元素的border之外显示的特性有点类似于overflow:hidden,就是明确的告知useragent子元素的内容将会不超过元素的边界,所以超出的部分不需要渲染。简单的例子,假设元素结构如下:
Coco
.container{contain:paint;border:1pxsolidred;}p{left:-100px;}看看contain:paint设置和未设置时会发生什么:CodePenDemo--contain:paintDemoSetcontain:paint元素在设置contain:paint时不会渲染他们在屏幕外。通过使用contain:paint,如果元素在屏幕外,用户代理会忽略这些元素的渲染,从而允许更快地渲染其他内容。contain:layoutcontain:layout:一个带有contain:layout的元素设置了一个布局约束,意思是通知UserAgent元素内部的样式变化不会引起元素外部的样式变化,反之亦然。该值打开元素的布局包含。这确保了包含框出于布局目的是完全不透明的;外部的任何东西都不能影响它的内部布局,反之亦然。启用contain:layout可以潜在地将每帧需要渲染的元素数量减少到少数,而不是重新渲染整个文档,从而为浏览器节省大量不必要的工作并显着提高性能。使用contain:layout,开发人员可以指定对该元素的任何后代的任何更改都不会影响任何外部元素的布局,反之亦然。所以浏览器只计算内部元素的位置(如果它被修改),其余的DOM保持不变。所以这意味着帧渲染管道中的布局过程会更快。存在的问题描述的很好,但是在实际的Demo测试中(截至2021/04/27,Chrome90.0.4430.85),仅仅单独使用contain:layout并没有验证得到上述好的结果。如果设置了contain:layout的指定元素,则对该元素的任何后代的任何更改仍将影响任何外部元素的布局。点击红框会添加一个