要点
新的 CSS Containment 属性让开发者可以限制浏览器的样式、布局和绘制工作的范围。
它有几个值,其语法如下所示:
contain: none | strict | content | [ size || layout || style || paint ]
我们已在 Chrome 52+ 和 Opera 40+ 中支持此版本(由 Firefox 提供公开支持),欢迎试用并告诉我们您的使用效果!
include 属性
在制作 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 包含”是一种新属性,其关键字包含“包含”,它支持以下四个值:
layout
paint
size
style
其中每个值都允许您限制浏览器需要执行的渲染工作量。我们来详细了解一下每种方法。
布局(包含:布局)
与 contain: paint
一样,布局包含可能是包含的最大优势。
布局通常是限定在文档范围内的,会根据 DOM 的大小按比例进行缩放,因此,如果您更改某个元素的 left
属性,则可能需要检查 DOM 中的每个元素。
在此处启用包含性可将元素数量减少至少数几个,而不是整个文档,从而为浏览器节省大量不必要的工作,并显著提高性能。
颜料(包含:颜料)
作用域绘制是控制的另一个极为有用的好处。颜料遏制本质上是裁剪相关元素,但它也有一些其他副作用:
- 它充当绝对定位和固定位置元素的包含块。这意味着,所有子元素都会根据具有
contain: paint
的元素定位,而不是任何其他父元素,比如文档。 - 它会变为堆叠上下文。这意味着,
z-index
之类的内容会对元素产生影响,并且子项会根据新的上下文堆叠在一起。 - 它将成为新的格式设置上下文。这意味着,举例来说,如果您有一个包含绘制包含的块级元素,系统会将其视为一个新的独立布局环境。这意味着,元素外部的布局通常不会影响所含元素的子元素。
尺寸(包含:尺寸)
contain: size
的含义是,元素的子项不会影响父项的尺寸,并且将使用其推断或声明的尺寸。因此,如果您设置 contain: size
,但未指定元素尺寸(直接或通过 Flex 属性指定),其渲染尺寸将为 0x0 像素!
尺寸包含实际上是一项复杂繁琐的衡量手段,旨在确保您不依赖子元素来确定尺寸,但其本身并不会带来太大的性能优势。
样式(包含:style)
很难预测更改元素样式会对 DOM 树造成什么影响。例如 CSS 计数器,更改子级中的计数器可能会影响文档中其他位置使用的相同名称的计数器值。设置 contain: style
后,样式更改不会回传到包含的元素。
特别要清楚一点,contain: style
不提供的是从 Shadow DOM 中获取的作用域样式设置;这里的包含只是为了限制在更改样式时要考虑的树部分,而不是在声明样式时考虑的。
严格和内容包含
您还可以组合关键字(如 contain: layout paint
),这样只会将这些行为应用于某个元素。不过,contains 还支持另外两个值:
contain: strict
的含义与contain: size layout paint
相同contain: content
的含义与contain: layout paint
相同
如果您提前知道元素的尺寸(或希望保留其尺寸),那么使用严格包含是非常有用的,但请注意,如果您声明严格包含(不含尺寸),由于隐含尺寸包含,该元素可能会呈现为 0x0 像素的方框。
另一方面,内容包含可显著改进范围,但您无需提前了解或指定元素的尺寸。
在这二者中,contain: content
是您应默认使用的一个。当 contain: content
无法满足您的需求时,您应将严格管控措施视为一种更有效的应急方法。
请告诉我们您的使用情况
“包含”是一个不错的方法,可向浏览器指明您打算在网页中隔离什么。欢迎使用 Chrome 52 及以上版本来试用,并告诉我们您取得的成效!