现代浏览器在渲染网页复杂的 HTML、CSS 和 JavaScript 代码方面效率显著提升,只需几毫秒即可将代码转换为可用的页面。
那么,前端开发者如何进一步提升浏览器渲染速度呢?除了那些容易被遗忘的最佳实践(尤其是在我们对生成的代码控制有限的情况下),例如:精简 CSS 选择器,保持 HTML 结构扁平化,以及谨慎操作 JavaScript 中的 HTML 和 CSS 等,我们还可以利用 CSS 的 contain
属性。
contain
属性允许开发者指定一个元素及其内容在多大程度上独立于文档树的其余部分。这使得浏览器能够仅对 DOM 的有限区域(而非整个页面)重新计算布局、样式、绘制、大小或它们的任意组合,从而带来明显的性能提升。
简单来说,contain
属性可以为浏览器提供有关页面上各个元素之间关系的提示,这些元素通常是包含内容的容器元素,即使这些内容是动态的。例如,在单页应用 (SPA) 中,动态内容经常在页面中插入和删除,通常与页面上的其他内容无关。
浏览器无法预测 JavaScript 插入和删除页面内容可能导致的未来布局变化。即使是简单的操作,例如向元素添加类名、动画化 DOM 元素或获取元素尺寸,都可能导致页面重排和重绘,这些操作代价高昂,应尽量避免或减少。
开发者可以根据页面设计的用户体验来预测可能的未来变化,例如用户点击按钮时,会调用数据插入到当前视图中某个 div 元素中。我们知道这是可能的,但浏览器不知道。我们也知道,将数据插入该 div 元素很可能不会改变页面上其他元素的视觉效果或其他方面。
浏览器开发者已经花费大量时间优化浏览器以处理这种情况。虽然有各种方法可以帮助浏览器更高效地处理这种情况,但更直接的提示会更有帮助。contain
属性为我们提供了一种提供这些提示的方法。
contain
属性的各种用法
contain
属性有三个值,可以单独使用或组合使用:size
、layout
和 paint
。它还有两个简写值,用于常见的组合:strict
和 content
。让我们了解一下每个值的含义。
需要注意的是,规范中涵盖了每个值的许多规则和边缘情况。在大多数情况下,这些规则可能不会引起太多关注。但是,如果您得到意外的结果,那么快速查看规范可能会有帮助。
规范中还有一种样式包含类型,本文不会介绍。原因是目前这种样式包含类型被认为价值不大,并且目前有被从规范中移除的风险。
size
包含
size
包含很容易解释。当包含此包含的容器参与布局计算时,浏览器可以跳过相当一部分计算,因为它会忽略该容器的子元素。预期容器将具有设置的高度和宽度;否则,它将折叠,并且这是页面布局中唯一考虑的因素。它被视为没有任何内容。
请注意,子元素可能会影响其容器的大小,具体取决于容器的样式。在计算布局时必须考虑这一点;使用 size
包含,很可能不会考虑这一点。一旦容器相对于页面的大小已确定,则将计算其子元素的布局。
size
包含本身并没有提供多少优化。它通常与其他值组合使用。
但是,它可以提供的一个好处是帮助处理根据容器大小更改容器子元素的 JavaScript,例如容器查询类型的情况。在某些情况下,根据容器的大小更改子元素可能会导致容器在对子元素进行更改后更改大小。由于容器大小的更改可能会触发子元素的另一次更改,因此您最终可能会出现更改循环。size
包含可以帮助防止这种循环。
这是一个关于此调整大小循环概念的完全人为的示例:(此处应插入代码示例,展示 size
包含如何防止调整大小循环)
layout
包含
layout
包含告诉浏览器外部元素既不影响容器元素的内部布局,也不影响容器元素的内部布局影响外部元素。因此,当浏览器进行布局计算时,它可以假设具有 layout
包含的各种元素不会影响其他元素。这可以减少需要执行的计算量。
另一个好处是,如果容器在屏幕外或被遮挡,则相关的计算可以延迟或降低优先级。规范提供的一个示例是:
[…] 例如,如果包含框位于块容器的末尾附近,而您正在查看块容器的开头
具有 layout
包含的容器成为绝对或固定位置子元素的包含块。这与对容器应用相对位置相同。因此,请记住在应用此类型的包含时如何影响容器的子元素。
同样,容器获得新的堆叠上下文,因此 z-index
的使用方式与应用相对、绝对或固定位置相同。但是,设置 top
、right
、bottom
或 left
属性对容器没有影响。
这是一个简单的例子:(此处应插入代码示例,展示 layout
包含如何影响布局和堆叠上下文)
paint
包含
paint
包含告诉浏览器容器的子元素永远不会绘制在容器框尺寸的边界之外。这类似于在容器上设置 overflow: hidden;
,但有一些区别。
首先,容器与在 layout
包含下的处理方式相同:它成为具有自身堆叠上下文的包含块。因此,在 paint
包含中定位的子元素将在位置方面尊重容器。如果我们要复制上面的 layout
包含演示但改为使用 paint
包含,结果将大致相同。不同之处在于,当应用包含时,紫色线不会溢出容器,而是在容器的边框框处被裁剪。
paint
包含的另一个有趣的好处是,如果浏览器可以检测到容器本身在视口中不可见,则它可以跳过该元素的子元素的绘制计算。如果容器不在视口中或以某种方式被遮挡,那么可以保证其子元素也不可见。例如,考虑一个通常位于页面左侧屏幕外的导航菜单,当点击按钮时它会滑入。当该菜单处于其正常的屏幕外状态时,浏览器只需跳过尝试绘制其内容。
各种包含的组合使用
这三种包含提供了影响浏览器执行的渲染计算部分的不同方法。size
包含告诉浏览器,当其内容更改时,此容器不应导致页面上的位置偏移。layout
包含告诉浏览器,此容器的子元素不应在其容器外部的元素中导致布局更改,反之亦然。paint
包含告诉浏览器,此容器的内容永远不会绘制在容器尺寸之外,并且如果容器被遮挡,则根本不要绘制内容。
由于每个包含都提供不同的优化,因此将某些包含组合在一起是有意义的。规范实际上允许这样做。例如,我们可以将 layout
和 paint
组合使用作为 contain
属性的值,如下所示:
.el { contain: layout paint; }
由于这是非常明显的事情,规范实际上提供了两个简写值:
content
值将是 Web 项目中最常用的值,其中包含许多动态元素,例如随着时间的推移或用户活动而更改内容的大型多个容器。
strict
值对于具有定义大小且永远不会更改大小的容器(即使内容更改)很有用。一旦到位,它将保持预期的尺寸。一个简单的例子是一个包含第三方外部广告内容的 div,其尺寸由行业定义,与页面上的任何其他 DOM 元素无关。
性能优势
这部分文章很难解释。问题在于关于性能优势的 视觉 效果不多。大多数好处都是幕后优化,帮助浏览器决定在布局或绘制更改时该做什么。
为了展示 contain
属性的性能优势,我做了一个简单的例子,它更改了具有多个子元素的元素的字体大小。这种更改通常会触发重新布局,这也会导致页面重绘。该示例涵盖了 none
、content
和 strict
的 contain
值。(此处应插入代码示例和性能测试结果)
布局一次,绘制两次
请耐心听我解释。我保证它会有意义。
我将使用上面的演示作为以下描述的基础。如果您希望继续学习,请访问演示的完整版本并打开 DevTools。请注意,在运行性能工具后,您必须打开“frame”而不是“main”时间线的详细信息才能看到我即将描述的内容。
我实际上是从“fullpage”版本中截取屏幕截图,因为 DevTools 在该版本中效果更好。也就是说,“full”常规版本应该提供大致相同的想法。
在没有包含的任务的事件日志中,绘制事件只触发一次。通常,事件不会花费太长时间,范围从 0.2 毫秒到 3.6 毫秒不等。更深入的细节是它变得有趣的地方。在这些细节中,它指出绘制区域是整个页面。在事件日志中,如果您将鼠标悬停在绘制事件上,DevTools 甚至会突出显示已绘制的页面区域。在这种情况下,尺寸将是浏览器视口的尺寸。它还会注意到绘制的图层根。
请注意,图像左侧的页面区域已突出显示,即使在紫色框之外也是如此。在右侧,是绘制到屏幕的尺寸。在这种情况下,大约是视口的尺寸。为了以后进行比较,请注意 #document 作为图层根。
请记住,浏览器具有某些元素的图层概念,以帮助绘制。图层通常用于由于新的堆叠上下文而可能相互重叠的元素。一个例子是应用 position: relative;
和 z-index: 1;
到元素的方式将导致浏览器将该元素创建为一个新图层。contain
属性具有相同的效果。
DevTools 中有一个名为“rendering”的部分,它提供各种工具来查看浏览器如何渲染页面。当选择名为“Layer borders”的复选框时,我们可以根据包含看到不同的内容。当包含为 none
时,您应该看不到超出典型静态网页图层的图层。选择 content
或 strict
,您可以看到紫色框转换为它自己的图层,并且页面的其余图层相应地发生变化。(此处应插入屏幕截图,展示不同包含类型下的图层)
我之前提到过,content
和 strict
都会导致绘制事件触发两次。这是因为出于两个不同的原因执行了两个不同的绘制过程。在我的演示中,第一个事件用于紫色框,第二个事件用于紫色框的内容。
通常,第一个事件将绘制紫色框并将该框的尺寸报告为事件的一部分。该框现在是它自己的图层,并享受适用的好处。
第二个事件用于框的内容,因为它们是滚动元素。正如规范所解释的那样;由于堆叠上下文是保证的,因此滚动元素可以绘制到单个 GPU 图层中。第二个事件中报告的尺寸更高,是滚动元素的高度。可能甚至更窄以腾出空间用于滚动条。
请注意这两个图像右侧尺寸的差异。此外,这两个事件的图层根都是 main.change 而不是上面看到的 #document。紫色框是一个主元素,因此只绘制了该元素而不是整个文档。您可以看到突出显示的框而不是整个页面。
这样做的好处是,通常当滚动元素进入视野时,必须绘制它们。包含中的滚动元素已经被绘制,因此在进入视野时不需要再次绘制它们。因此,我们也获得了一些滚动优化。
同样,这可以在演示中看到。(此处应插入屏幕截图,展示不同包含类型下的滚动性能)
一个有趣的意外发现
当我尝试上面的演示并了解绘制和滚动性能方面的工作方式时,我遇到一个有趣的问题。在一个测试中,我在页面中央有一个简单的框,但样式最少。它本质上是一个带有大量文本内容的滚动元素。我将内容包含应用于容器元素,但我没有看到上面描述的滚动性能优势。
该容器用“repaints on scroll”叠加层标记,并且绘制闪烁与未应用包含的情况相同,即使我知道实际上内容包含已应用于该容器。因此,我开始将我的简单测试与上面讨论的样式更丰富的版本进行比较。
我最终发现,如果容器的 background-color
为透明,则不会出现包含滚动性能优势。
我运行了一个类似的性能测试,我将更改内容的字体大小以触发重新布局和重绘。两个测试的结果大致相同,唯一的区别是第一个测试的 background-color
为透明,第二个测试的 background-color
为适当的颜色。从数字来看,幕后计算仍然更高效;只有绘制事件不同。似乎元素在具有透明 background-color
的情况下不会成为绘制计算中的自己的图层。
第一个测试运行在事件日志中只有一个绘制事件。第二个测试运行有两个绘制事件,正如我预期的那样。如果没有该背景颜色,浏览器似乎决定跳过包含的图层方面。我甚至发现通过使用与元素后面颜色相同的颜色来伪造透明度也能正常工作。我的猜测是,如果容器的背景是透明的,那么它必须依赖于下面的任何内容,这使得不可能将容器分离到它自己的绘制图层中。(此处应插入屏幕截图,展示透明背景颜色与不透明背景颜色下的不同结果)
我制作了测试演示的另一个版本,该版本将容器元素的 background-color
从透明更改为与正文背景颜色相同的颜色。以下是使用 DevTools 中“Rendering”面板中的各种选项时的两个屏幕截图。(此处应插入屏幕截图,展示透明背景颜色与不透明背景颜色下的不同结果)
总结
本文介绍了 CSS contain
属性的基础知识,包括其值、好处和潜在的性能提升。将此属性应用于 HTML 中的某些元素有一些好处;哪些元素需要应用此属性取决于您。至少,这就是我的理解,因为我不知道任何具体的指导。一般的想法是将其应用于其他元素的容器,尤其是那些具有某种动态方面的容器。
一些可能的场景:CSS 网格的网格区域、包含第三方内容的元素以及根据用户交互具有动态内容的容器。在这些情况下使用该属性应该不会有任何害处,假设您不是试图包含实际上依赖于该包含之外的另一个元素的元素。
浏览器支持非常强大。Safari 是目前唯一一个不支持的浏览器。无论如何,您仍然可以使用该属性,因为如果浏览器不理解该属性或其值,它只会简单地跳过该代码而不会出错。
因此,请随意开始包含您的内容!
以上是讓我們深入研究CSS包含屬性的詳細內容。更多資訊請關注PHP中文網其他相關文章!

具有CSS的自定義光標很棒,但是我們可以將JavaScript提升到一個新的水平。使用JavaScript,我們可以在光標狀態之間過渡,將動態文本放置在光標中,應用複雜的動畫並應用過濾器。

互動CSS動畫和元素相互啟動的元素在2025年似乎更合理。雖然不需要在CSS中實施乒乓球,但CSS的靈活性和力量的增加,可以懷疑Lee&Aver Lee有一天會成為一種

有關利用CSS背景濾波器屬性來樣式用戶界面的提示和技巧。您將學習如何在多個元素之間進行背景過濾器,並將它們與其他CSS圖形效果集成在一起以創建精心設計的設計。

好吧,事實證明,SVG的內置動畫功能從未按計劃進行棄用。當然,CSS和JavaScript具有承載負載的能力,但是很高興知道Smil並沒有像以前那樣死在水中

是的,讓#039;跳上文字包裝:Safari Technology Preview In Pretty Landing!但是請注意,它與在鉻瀏覽器中的工作方式不同。

此CSS-tricks更新了,重點介紹了年鑑,最近的播客出現,新的CSS計數器指南以及增加了幾位新作者,這些新作者貢獻了有價值的內容。

在大多數情況下,人們展示了@Apply的@Apply功能,其中包括Tailwind的單個property實用程序之一(會改變單個CSS聲明)。當以這種方式展示時,@Apply聽起來似乎很有希望。如此明顯


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

記事本++7.3.1
好用且免費的程式碼編輯器

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境