目錄
各种包含的组合使用
性能优势
布局一次,绘制两次
一个有趣的意外发现
总结
首頁 web前端 css教學 讓我們深入研究CSS包含屬性

讓我們深入研究CSS包含屬性

Apr 06, 2025 am 10:30 AM

Let's Take a Deep Dive Into the CSS Contain Property

现代浏览器在渲染网页复杂的 HTML、CSS 和 JavaScript 代码方面效率显著提升,只需几毫秒即可将代码转换为可用的页面。

那么,前端开发者如何进一步提升浏览器渲染速度呢?除了那些容易被遗忘的最佳实践(尤其是在我们对生成的代码控制有限的情况下),例如:精简 CSS 选择器,保持 HTML 结构扁平化,以及谨慎操作 JavaScript 中的 HTML 和 CSS 等,我们还可以利用 CSS 的 contain 属性。

contain 属性允许开发者指定一个元素及其内容在多大程度上独立于文档树的其余部分。这使得浏览器能够仅对 DOM 的有限区域(而非整个页面)重新计算布局、样式、绘制、大小或它们的任意组合,从而带来明显的性能提升。

简单来说,contain 属性可以为浏览器提供有关页面上各个元素之间关系的提示,这些元素通常是包含内容的容器元素,即使这些内容是动态的。例如,在单页应用 (SPA) 中,动态内容经常在页面中插入和删除,通常与页面上的其他内容无关。

浏览器无法预测 JavaScript 插入和删除页面内容可能导致的未来布局变化。即使是简单的操作,例如向元素添加类名、动画化 DOM 元素或获取元素尺寸,都可能导致页面重排和重绘,这些操作代价高昂,应尽量避免或减少。

开发者可以根据页面设计的用户体验来预测可能的未来变化,例如用户点击按钮时,会调用数据插入到当前视图中某个 div 元素中。我们知道这是可能的,但浏览器不知道。我们也知道,将数据插入该 div 元素很可能不会改变页面上其他元素的视觉效果或其他方面。

浏览器开发者已经花费大量时间优化浏览器以处理这种情况。虽然有各种方法可以帮助浏览器更高效地处理这种情况,但更直接的提示会更有帮助。contain 属性为我们提供了一种提供这些提示的方法。

contain 属性的各种用法

contain 属性有三个值,可以单独使用或组合使用:sizelayoutpaint。它还有两个简写值,用于常见的组合:strictcontent。让我们了解一下每个值的含义。

需要注意的是,规范中涵盖了每个值的许多规则和边缘情况。在大多数情况下,这些规则可能不会引起太多关注。但是,如果您得到意外的结果,那么快速查看规范可能会有帮助。

规范中还有一种样式包含类型,本文不会介绍。原因是目前这种样式包含类型被认为价值不大,并且目前有被从规范中移除的风险。

size 包含

size 包含很容易解释。当包含此包含的容器参与布局计算时,浏览器可以跳过相当一部分计算,因为它会忽略该容器的子元素。预期容器将具有设置的高度和宽度;否则,它将折叠,并且这是页面布局中唯一考虑的因素。它被视为没有任何内容。

请注意,子元素可能会影响其容器的大小,具体取决于容器的样式。在计算布局时必须考虑这一点;使用 size 包含,很可能不会考虑这一点。一旦容器相对于页面的大小已确定,则将计算其子元素的布局。

size 包含本身并没有提供多少优化。它通常与其他值组合使用。

但是,它可以提供的一个好处是帮助处理根据容器大小更改容器子元素的 JavaScript,例如容器查询类型的情况。在某些情况下,根据容器的大小更改子元素可能会导致容器在对子元素进行更改后更改大小。由于容器大小的更改可能会触发子元素的另一次更改,因此您最终可能会出现更改循环。size 包含可以帮助防止这种循环。

这是一个关于此调整大小循环概念的完全人为的示例:(此处应插入代码示例,展示 size 包含如何防止调整大小循环)

layout 包含

layout 包含告诉浏览器外部元素既不影响容器元素的内部布局,也不影响容器元素的内部布局影响外部元素。因此,当浏览器进行布局计算时,它可以假设具有 layout 包含的各种元素不会影响其他元素。这可以减少需要执行的计算量。

另一个好处是,如果容器在屏幕外或被遮挡,则相关的计算可以延迟或降低优先级。规范提供的一个示例是:

[…] 例如,如果包含框位于块容器的末尾附近,而您正在查看块容器的开头

具有 layout 包含的容器成为绝对或固定位置子元素的包含块。这与对容器应用相对位置相同。因此,请记住在应用此类型的包含时如何影响容器的子元素。

同样,容器获得新的堆叠上下文,因此 z-index 的使用方式与应用相对、绝对或固定位置相同。但是,设置 toprightbottomleft 属性对容器没有影响。

这是一个简单的例子:(此处应插入代码示例,展示 layout 包含如何影响布局和堆叠上下文)

paint 包含

paint 包含告诉浏览器容器的子元素永远不会绘制在容器框尺寸的边界之外。这类似于在容器上设置 overflow: hidden;,但有一些区别。

首先,容器与在 layout 包含下的处理方式相同:它成为具有自身堆叠上下文的包含块。因此,在 paint 包含中定位的子元素将在位置方面尊重容器。如果我们要复制上面的 layout 包含演示但改为使用 paint 包含,结果将大致相同。不同之处在于,当应用包含时,紫色线不会溢出容器,而是在容器的边框框处被裁剪。

paint 包含的另一个有趣的好处是,如果浏览器可以检测到容器本身在视口中不可见,则它可以跳过该元素的子元素的绘制计算。如果容器不在视口中或以某种方式被遮挡,那么可以保证其子元素也不可见。例如,考虑一个通常位于页面左侧屏幕外的导航菜单,当点击按钮时它会滑入。当该菜单处于其正常的屏幕外状态时,浏览器只需跳过尝试绘制其内容。

各种包含的组合使用

这三种包含提供了影响浏览器执行的渲染计算部分的不同方法。size 包含告诉浏览器,当其内容更改时,此容器不应导致页面上的位置偏移。layout 包含告诉浏览器,此容器的子元素不应在其容器外部的元素中导致布局更改,反之亦然。paint 包含告诉浏览器,此容器的内容永远不会绘制在容器尺寸之外,并且如果容器被遮挡,则根本不要绘制内容。

由于每个包含都提供不同的优化,因此将某些包含组合在一起是有意义的。规范实际上允许这样做。例如,我们可以将 layoutpaint 组合使用作为 contain 属性的值,如下所示:

.el {
  contain: layout paint;
}
登入後複製

由于这是非常明显的事情,规范实际上提供了两个简写值:

content 值将是 Web 项目中最常用的值,其中包含许多动态元素,例如随着时间的推移或用户活动而更改内容的大型多个容器。

strict 值对于具有定义大小且永远不会更改大小的容器(即使内容更改)很有用。一旦到位,它将保持预期的尺寸。一个简单的例子是一个包含第三方外部广告内容的 div,其尺寸由行业定义,与页面上的任何其他 DOM 元素无关。

性能优势

这部分文章很难解释。问题在于关于性能优势的 视觉 效果不多。大多数好处都是幕后优化,帮助浏览器决定在布局或绘制更改时该做什么。

为了展示 contain 属性的性能优势,我做了一个简单的例子,它更改了具有多个子元素的元素的字体大小。这种更改通常会触发重新布局,这也会导致页面重绘。该示例涵盖了 nonecontentstrictcontain 值。(此处应插入代码示例和性能测试结果)

布局一次,绘制两次

请耐心听我解释。我保证它会有意义。

我将使用上面的演示作为以下描述的基础。如果您希望继续学习,请访问演示的完整版本并打开 DevTools。请注意,在运行性能工具后,您必须打开“frame”而不是“main”时间线的详细信息才能看到我即将描述的内容。

我实际上是从“fullpage”版本中截取屏幕截图,因为 DevTools 在该版本中效果更好。也就是说,“full”常规版本应该提供大致相同的想法。

在没有包含的任务的事件日志中,绘制事件只触发一次。通常,事件不会花费太长时间,范围从 0.2 毫秒到 3.6 毫秒不等。更深入的细节是它变得有趣的地方。在这些细节中,它指出绘制区域是整个页面。在事件日志中,如果您将鼠标悬停在绘制事件上,DevTools 甚至会突出显示已绘制的页面区域。在这种情况下,尺寸将是浏览器视口的尺寸。它还会注意到绘制的图层根。

请注意,图像左侧的页面区域已突出显示,即使在紫色框之外也是如此。在右侧,是绘制到屏幕的尺寸。在这种情况下,大约是视口的尺寸。为了以后进行比较,请注意 #document 作为图层根。

请记住,浏览器具有某些元素的图层概念,以帮助绘制。图层通常用于由于新的堆叠上下文而可能相互重叠的元素。一个例子是应用 position: relative;z-index: 1; 到元素的方式将导致浏览器将该元素创建为一个新图层。contain 属性具有相同的效果。

DevTools 中有一个名为“rendering”的部分,它提供各种工具来查看浏览器如何渲染页面。当选择名为“Layer borders”的复选框时,我们可以根据包含看到不同的内容。当包含为 none 时,您应该看不到超出典型静态网页图层的图层。选择 contentstrict,您可以看到紫色框转换为它自己的图层,并且页面的其余图层相应地发生变化。(此处应插入屏幕截图,展示不同包含类型下的图层)

我之前提到过,contentstrict 都会导致绘制事件触发两次。这是因为出于两个不同的原因执行了两个不同的绘制过程。在我的演示中,第一个事件用于紫色框,第二个事件用于紫色框的内容。

通常,第一个事件将绘制紫色框并将该框的尺寸报告为事件的一部分。该框现在是它自己的图层,并享受适用的好处。

第二个事件用于框的内容,因为它们是滚动元素。正如规范所解释的那样;由于堆叠上下文是保证的,因此滚动元素可以绘制到单个 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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

帶有粘性定位的堆疊卡和一點點的雜物 帶有粘性定位的堆疊卡和一點點的雜物 Apr 03, 2025 am 10:30 AM

前幾天,我發現了科里·金尼文(Corey Ginnivan)網站上的這一點,當您滾動時,彼此之間的卡片堆放集。

Google字體可變字體 Google字體可變字體 Apr 09, 2025 am 10:42 AM

我看到Google字體推出了新設計(Tweet)。與上一次大型重新設計相比,這感覺更加迭代。我幾乎無法分辨出區別

如何使用HTML,CSS和JavaScript創建動畫倒計時計時器 如何使用HTML,CSS和JavaScript創建動畫倒計時計時器 Apr 11, 2025 am 11:29 AM

您是否曾經在項目上需要一個倒計時計時器?對於這樣的東西,可以自然訪問插件,但實際上更多

為什麼Flex佈局中的紫色斜線區域會被誤認為是'溢出空間”? 為什麼Flex佈局中的紫色斜線區域會被誤認為是'溢出空間”? Apr 05, 2025 pm 05:51 PM

關於Flex佈局中紫色斜線區域的疑問在使用Flex佈局時,你可能會遇到一些令人困惑的現象,比如在開發者工具(d...

如何通過CSS選擇第一個類名為item的子元素? 如何通過CSS選擇第一個類名為item的子元素? Apr 05, 2025 pm 11:24 PM

在元素個數不固定的情況下如何通過CSS選擇第一個指定類名的子元素在處理HTML結構時,常常會遇到元素個數不�...

HTML數據屬性指南 HTML數據屬性指南 Apr 11, 2025 am 11:50 AM

您想了解的有關HTML,CSS和JavaScript中數據屬性的所有信息。

使Sass更快的概念證明 使Sass更快的概念證明 Apr 16, 2025 am 10:38 AM

在一個新項目開始時,Sass彙編發生在眼睛的眨眼中。感覺很棒,尤其是當它與browsersync配對時,它重新加載

在前端開發中,如何使用CSS和JavaScript實現類似Windows 10設置界面的探照燈效果? 在前端開發中,如何使用CSS和JavaScript實現類似Windows 10設置界面的探照燈效果? Apr 05, 2025 pm 10:21 PM

在前端開發中如何實現類似Windows...

See all articles