Chrome 52 中的 CSS 包含

Paul Lewis

要点

新增的 CSS Containment 属性可让开发者限制浏览器样式、布局和绘制工作的范围。

CSS Containment。更新前:布局用时 59.6 毫秒。之后:布局用时 0.05 毫秒

它有几个值,因此其语法如下所示:

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

Chrome 52+ 和 Opera 40+(并且来自 Firefox 的公开支持)中可以使用了,快来体验一下,将您的想法告诉我们!

包含属性

在构建 Web 应用甚至是复杂网站时,一个关键的性能挑战是限制样式、布局和绘制的效果。通常,整个 DOM 都被视为计算工作“在范围内”,这可能意味着尝试在 Web 应用中创建独立的“视图”可能会比较棘手:对 DOM 某个部分进行更改可能会影响其他部分,并且无法告知浏览器哪些元素应该在范围内或不在范围内。

例如,假设 DOM 的一部分如下所示:

    <section class="view">
      Home
    </section>

    <section class="view">
      About
    </section>

    <section class="view">
      Contact
    </section>

您要将一个新元素附加到一个视图,这将触发样式、布局和绘制:

    <section class="view">
      Home
    </section>

    <section class="view">
      About
      <div class="newly-added-element">Check me out!</div>
    </section>

    <section class="view">
      Contact
    </section>

不过,在这种情况下,整个 DOM 实际在作用域内,这意味着样式、布局和绘制计算必须考虑所有元素(无论是否已更改)。DOM 越大,涉及的计算工作就越多,这意味着您的应用可能会对用户输入无响应。

值得高兴的是,现代浏览器在自动限制样式、布局和绘制工作的范围方面都变得非常智能,这意味着您无需进行任何操作即可加快处理速度。

更好的消息是,有一种新的 CSS 属性将范围控制移交给开发者:Containment

CSS Containment 是一个新属性,其关键字包含资源,此属性支持四个值:

  • layout
  • paint
  • size
  • style

每个值都可用于限制浏览器需要完成的呈现工作量。让我们详细了解一下每个值。

布局(包含:布局)

布局包含可能是与 contain: paint 一起的最大优势。

布局通常是文档级范围的,因此它会根据 DOM 的大小按比例进行缩放,因此,如果您更改元素的 left 属性,则可能需要检查 DOM 中的每个元素。

在此处启用包含功能可能会将元素数量减少到一小部分,而不是整个文档,从而为浏览器节省大量不必要的工作,并显著提升性能。

颜料(包含:颜料)

作用域绘制是封闭的另一个极为有用的优势。颜料容器实际上会裁剪相关元素,但它也有一些其他副作用:

  • 它充当绝对定位和固定位置元素的容器块。这意味着所有子元素均根据具有 contain: paint 的元素进行放置,而不是根据任何其他父元素(例如文档)进行定位。
  • 它会变成一个堆叠的上下文。这意味着,z-index 等元素会对元素产生影响,并且系统会根据新的上下文堆叠子元素。
  • 它成为一种新的格式设置上下文。这意味着,例如,如果您有一个包含绘制控制机制的块级元素,系统会将其视为一个新的独立布局环境。这意味着,元素外部的布局通常不会影响所包含元素的子元素。

尺寸(包含:尺寸)

contain: size 意味着该元素的子元素不会影响父元素的尺寸,并且其推断或声明的尺寸将使用。因此,如果设置 contain: size 但未为元素指定尺寸(直接指定或通过 flex 属性指定),它将以 0x0 像素呈现!

尺寸包含能力实际上是一项用“带大括号”括住的措施,可确保您不依赖子元素来确定尺寸,但其本身并不能带来太多性能优势。

样式(包含:样式)

很难预测改变元素样式对 DOM 树造成的什么影响会备份树。例如,在 CSS 计数器等部分中,更改子级中的计数器可能会影响文档中其他位置使用的同名计数器值。设置 contain: style 后,样式更改不会回传到所包含元素之后。

简而言之,contain: style 不提供与 Shadow DOM 相同的作用域样式设置;这里的包含操作仅仅是对样式变更时要考虑的树部分进行限制,而不是在声明样式时限制这些部分。

严格限制和内容控制

您还可以组合关键字(例如 contain: layout paint),这样只会将这些行为应用于元素。但是“包含”还支持另外两个值:

  • contain: strict 表示与 contain: size layout paint 相同
  • contain: content 表示与 contain: layout paint 相同

如果您提前知道元素的大小(或希望保留其尺寸),使用严格限制会非常有用,但是请注意,如果您声明严格包含不包含尺寸,由于包含隐式大小,元素可能会渲染为一个 0x0 像素的框。

另一方面,内容包含可显著改进作用域,但无需提前了解或指定元素的尺寸。

在这两者中,应默认使用 contain: content。当 contain: content 的强度不足以满足您的需求时,您应该将严格控制视为一种更好的避难措施。

让我们了解您的进展情况

如需开始向浏览器指明您打算在网页内隔离什么,这是一种很棒的方法。欢迎在 Chrome 52 及更高版本中试用,并告知我们您的体验!