初探CSS的容器模块

特别声明:如果您喜欢小站的内容,可以点击年卡¥199.00元(原价: ¥598元)季卡¥78.00元(原价: ¥168元)月卡¥28.00元(原价: ¥68元)进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)

CSS的容器模块指的是CSS Containment Module,到目前为止主要分为 Level 1Level 2两个版本。在容器模块中主要包含了CSS的 containcontent-visibility 两个属性。这两个属性都可以帮助我们提高Web页面的性能,那么它们是如何工作的?我们在实际项目中又应该怎么使用呢?如果你感兴趣的话,请继续往下阅读。

重排和重绘

在开始介绍containcontent-visibility属性之前,我们先简单的了解两个重要概念:重排(Reflows)重绘(Repaints)

  • 重排(Reflows):当DOM的变化影响了元素的几何信息(DOM对象的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做 重排(重排也叫回流)
  • 重绘(Repaints):当一个元素外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,这个过程叫做 重绘

简单地回忆一下,浏览器在渲染一个页面时会经历像下图这样的一个过程:

也就是说,浏览器的渲染过程其实就是 将页面转换成像素显示到屏幕上,它大致会经历以下几个过程:

在Web页面的生命周期中,Web页面生成的时候,至少会渲染一次。在用户访问的过程中,还会不断触发重排和重绘。需要注意的是,重绘不一定需要重排,但重排必然导致重绘!不管页面发生了重绘还是重排,都会影响性能,其中最可怕的就是重排,会使我们付出高额的性能代价,所以我们应该尽量避免。

简单地说,修改DOM修改样式用户事件会导致Web页面重新渲染,也就触发重排重绘。JavaScript的一些操作会对DOM和样式进行修改,比如说offsetLeftoffsetTopoffsetWidthscrollBy()scrollTo()getComputedStyle()等,除了这些操作会触发重排和重绘之外,还有其他的一些JavaScript操作,具体的可以查阅:

有关于这方面更详细的介绍,还可以阅读@Charis Theodoulou的《Web Performance: Minimising DOM Reflow / Layout Shift》一文。

什么是CSS容器(Containment)

CSS容器模块主要目标是提高Web页面的渲染性能,它允许将子树(Subtree)和文档(Document)的其余部分隔离开来。这个规范引入了两个新的CSS属性:containcontent-visibility两个属性。浏览器引擎可以使用这些特性来对Web性能进行优化:

  • 当容器的内容发生变化时,浏览器考虑到其他元素可能也会发生变化,于是就会去检查页面中所有的元素。一直以来浏览器都是这么做的,大家都习以为常了。但从另一方面来说,开发者很清楚当前修改的元素是否独立、是否影响其他元素。因此如果开发者能把这个信息通过CSS告诉浏览器,那么浏览器就不需要再去考虑其他元素了,这就是非常完美的事情。而CSS容器模块中的contain属性就为我们提供了这种能力
  • CSS容器模块中的content-visibility属性会显著影响第一次下载和第一次渲染的速度。此外,你可以立即与新渲染的内容交互,而无需等待内容的其余部分加载。该属性强制用户代理跳过不在屏幕上的标记和绘制元素。实际上,它的工作方式类似于延迟加载,只是不加载资源,而是渲染资源

接下来,我们分别来探讨这两个属性的具体使用。

CSS contain属性

CSS的contain属性现在得到了众多主流浏览器的支持:

W3C规范是这样描述contain

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 user agents to utilize much stronger optimizations when rendering a page using contain properly, and allows authors to be confident that their page won’t accidentally fall into a slow code path due to an innocuous change.

大致的意思是: contain属性允许我们指定特定的DOM元素和它的子元素,让它们能够独立于整个DOM树结构之外。目的是能够让浏览器有能力只对部分元素进行重绘、重排,而不必每次针对整个页面

contain可接受的值:

contain: none | strict | content | [ size || layout || style || paint ]

其中nonecontain的默认值,在实际使用的时候,我们可以通过contain的其他五个值中的某一个来规定元素以何种方式独立于文档树:

  • layout :该值表示元素的内部布局不受外部的任何影响,同时该元素以及其内容也不会影响以上级
  • paint :该值表示元素的子级不能在该元素的范围外显示,该元素不会有任何内容溢出(或者即使溢出了,也不会被显示)
  • size :该值表示元素盒子的大小是独立于其内容,也就是说在计算该元素盒子大小的时候是会忽略其子元素
  • content :该值是contain: layout paint的简写
  • strict :该值是contain: layout paint size的简写

在上述这几个值中,sizelayoutpaint可以单独使用,也可以相互组合使用;另外contentstrict是组合值,即contentlayout paint的组合,strictlayout paint size的组合。

在规范中还有style类型,但style常被认为是没有什么价值,而且很有可能从规范中移除。

我们在这里只会围绕sizelayoutpaint三种类型展开。

size类型

先来看下个contain属性取值为size的示例效果。拿我们最为熟悉的手风琴效果为例:

为了更好的看出contain的效果,我们在手风琴的容器上添加一些样式:

.accordion__item {
    border: 1px dashed #015fcc;
    border-radius: 4px;
    box-shadow: 0 0px 1px 1px #015fcc;
}

当手风琴展开时,边框和阴影也会展开:

剩余80%内容付费后可查看

如需转载,烦请注明出处:https://www.w3cplus.com/css/deep-dive-into-css-contain.html

如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!

赏杯咖啡,鼓励他创作更多优质内容!
返回顶部