要点
利用新的 CSS Containment 属性,开发者可以限制浏览器的样式、布局和绘制工作的范围。
![CSS 包含。更新前:布局耗时 59.6 毫秒。之后:布局用时 0.05 毫秒](https://developer.chrome.google.cn/static/blog/css-containment/image/css-containment-before-dd44d7d4075ef.jpg?authuser=5&hl=fi)
它有几个值,因此其语法如下所示:
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 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
),这样只会将这些行为应用到某个元素。不过,“contains”还支持另外两个值:
contain: strict
的含义与contain: size layout paint
相同contain: content
的含义与contain: layout paint
相同
当您提前知道元素的尺寸(或希望保留其尺寸)时,使用严格包含式限制是非常有用的,但请注意,如果您声明了不含尺寸的严格包含,由于隐含的包含尺寸,元素可能会渲染为一个 0x0 像素的框。
另一方面,内容包含可以显著改进范围,但您无需提前知道或指定元素的尺寸。
在两者中,contain: content
是应默认使用的值。当 contain: content
强度不足以满足您的需求时,您应该将严格控制视为一种更有效的应急方法。
请告知我们您的进展
如需向浏览器指明您打算在网页内隔离什么内容,它是一种很好的方法。欢迎在 Chrome 52 及更高版本中试用,并告知我们您的使用体验!