关于前端:CSS新特性contain控制页面的重绘与重排

52次阅读

共计 3939 个字符,预计需要花费 10 分钟才能阅读完成。

在介绍新的 CSS 属性 contain 之前,读者首先须要理解什么是页面的重绘与重排。

之前曾经形容过很屡次了,还不太理解的能够先看看这个进步 CSS 动画性能的正确姿态。

OK,上面进入本文正题,

contain 为何?

contain 属性容许咱们指定特定的 DOM 元素和它的子元素,让它们可能独立于整个 DOM 树结构之外。目标是可能让浏览器有能力只对局部元素进行重绘、重排,而不用每次都针对整个页面。

The contain property allows an author to indicate that an element and its contents are, as much as possible, independent of the rest of the document tree. This allows the browser to recalculate layout, style, paint, size, or any combination of them for a limited area of the DOM and not the entire page.

contain 语法

看看它的语法:

{
  /* No layout containment. */
  contain: none;
  /* Turn on containment for layout, style, paint, and size. */
  contain: strict;
  /* Turn on containment for layout, style, and paint. */
  contain: content;
  /* Turn on size containment for an element. */
  contain: size;
  /* Turn on layout containment for an element. */
  contain: layout;
  /* Turn on style containment for an element. */
  contain: style;
  /* Turn on paint containment for an element. */
  contain: paint;
}

除去 none,取值还有 6 个,咱们一个一个来看看。

contain: size

contain: size: 设定了 contain: size 的元素的渲染不会受到其子元素内容的影响。

The value turns on size containment for the element. This ensures that the containing box can be laid out without needing to examine its descendants.

我开始看到这个定义也是一头雾水,光看定义很难明确到底是什么意思。还需实际一番:

假如咱们有如下简略构造:

<div class="container">
   
</div>
.container {
    width: 300px;
    padding: 10px;
    border: 1px solid red;
}

p {
    border: 1px solid #333;
    margin: 5px;
    font-size: 14px;
}

并且,借助 jQuery 实现每次点击容器增加一个 <p>Coco</p> 构造:

$('.container').on('click', e => {$('.container').append('<p>Coco</p>')
})

那么会失去如下后果:

能够看到,容器 .container 的高度是会随着元素的减少而减少的,这是失常的景象。

此刻,咱们给容器 .container 增加一个 contain: size,也就会呈现上述说的: 设定了 contain: size 的元素的渲染不会受到其子元素内容的影响

.container {
    width: 300px;
    padding: 10px;
    border: 1px solid red;
+   contain: size
}

再看看会产生什么:

失常而言,父元素的高度会因为子元素的增多而被撑高,而当初,子元素的变动不再影响父元素的款式布局,这就是 contain: size 的作用。

contain: style

接下来再说说 contain: stylecontain: layoutcontain: paint。先看看 contain: style。

截止至本文书写的过程中,contain: style 临时被移除了。

CSS Containment Module Level 1: Drop the at-risk“style containment”feature from this specification, move it Level 2。

嗯,官网说辞是因为存在某些危险,临时被移除,可能在标准的第二版会从新定义吧,那这个属性也暂且放一放。

contain: paint

contain: paint:设定了 contain: paint 的元素即是设定了布局限度,也就是说告知 User Agent,此元素的子元素不会在此元素的边界之外被展现,因而,如果元素不在屏幕上或以其余形式设定为不可见,则还能够保障其后辈不可见不被渲染。

This value turns on paint containment for the element. This ensures that the descendants of the containing box don’t display outside its bounds, so if an element is off-screen or otherwise not visible, its descendants are also guaranteed to be not visible.

这个略微好了解一点,先来看第一个个性:

设定了 contain: paint 的元素的子元素不会在此元素的边界之外被展现

  • 设定了 contain: paint 的元素的子元素不会在此元素的边界之外被展现

这个特点有点相似与 overflow: hidden,也就是明确告知用户代理,子元素的内容不会超出元素的边界,所以超出局部无需渲染。

简略示例,假如元素构造如下:

<div class="container">
    <p>Coco</p>
</div>
.container {
    contain: paint;
    border: 1px solid red;
}

p{left: -100px;}

咱们来看看,设定了 contain: paint 与没设定时会产生什么:

CodePen Demo — contain: paint Demo

设定了 contain: paint 的元素在屏幕之外时不会渲染绘制

通过应用 contain: paint,如果元素处于屏幕外,那么用户代理就会疏忽渲染这些元素,从而能更快的渲染其它内容。

contain: layout

contain: layout:设定了 contain: layout 的元素即是设定了布局限度,也就是说告知 User Agent,此元素外部的款式变动不会引起元素内部的款式变动,反之亦然。

This value turns on layout containment for the element. This ensures that the containing box is totally opaque for layout purposes; nothing outside can affect its internal layout, and vice versa.

启用 contain: layout 能够潜在地将每一帧须要渲染的元素数量缩小到多数,而不是从新渲染整个文档,从而为浏览器节俭了大量不必要的工作,并显着进步了性能。

应用 contain:layout,开发人员能够指定对该元素任何后辈的任何更改都不会影响任何内部元素的布局,反之亦然。

因而,浏览器仅计算外部元素的地位(如果对其进行了批改),而其余 DOM 放弃不变。因而,这意味着帧渲染管道中的布局过程将放慢。

存在的问题

形容很美妙,然而在理论 Demo 测试的过程中(截止至 2021/04/27,Chrome 90.0.4430.85),仅仅独自应用 contain:layout 并没有验证失去上述那么美妙的后果。

设定了 contain: layout 的指定元素,改元素的任何后辈的任何更改还是会影响任何内部元素的布局 ,点击红框会减少一条 <p>Coco<p> 元素插入到 container 中:

简略的代码如下:

<div class="container">
    <p>Coco</p>
    ...
</div>
<div class="g-test"></div>
html,
body {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    gap: 10px;
}

.container {
    width: 150px;
    padding: 10px;
    contain: layout;
    border: 1px solid red;
}

.g-test {
    width: 150px;
    height: 150px;
    border: 1px solid green;
}

CodePen Demo — contain: layout Demo

Can i Use — CSS Contain

截止至 2021-04-27,Can i Use 上的 CSS Contain 兼容性,曾经能够开始应用起来:

参考文献

  • CSS Containment Module Level 1
  • CSS containment
  • CSS Containment in Chrome 52

最初

好了,本文到此结束,心愿对你有帮忙 :)

想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 — iCSS 前端趣闻

更多精彩 CSS 技术文章汇总在我的 Github — iCSS,继续更新,欢送点个 star 订阅珍藏。

如果还有什么疑难或者倡议,能够多多交换,原创文章,文笔无限,满腹经纶,文中若有不正之处,万望告知。

正文完
 0