什么时候该在 CSS 中使用 contain 和 will-change?

Avatar of Chris Coyier
Chris Coyier on

DigitalOcean 为您的旅程各个阶段提供云产品。立即开始使用 $200 免费额度!

我在与 CSS 相关的性能方面有一些盲点。一个例子是 will-change 属性。这个名字很好。你告诉浏览器某个特定属性(或 scroll-position 或内容)将要发生变化。

.el {
  will-change: opacity;
}
.el.additional-hard-to-know-state {
  opacity: 0;
}

但这重要吗?我不知道。据我了解,它的作用是将 .el 转移到 GPU 上进行处理/渲染/绘制,而不是 CPU,这是一种速度提升。有点类似于经典的 transform: translate3d(0, 0, 0); hack。在上面的确切情况下,它在我看来并不重要。在我脑海中,opacity 是“最便宜”的动画之一,因此 will-change 没有特别的好处。或者它可能在某些浏览器或设备上明显起作用,而在其他设备上则不起作用?毕竟这是前端开发。

在 2014/2015 年左右,有一段时间关于 will-change 的文章激增,这些文章警告说存在奇怪的行为,例如堆叠上下文中的意外变化,以及要小心不要“过度使用”它。还有一些建议传播开来,说你永远不应该在 CSS 样式表中直接使用此属性;你应该在状态更改之前仅在 JavaScript 中应用它,然后在你不再需要它后将其删除。

我不知道这些事情是否仍然适用。抱歉!我渴望阅读一篇关于 will-change 的 2022 年深度分析文章。我们有能力进行这种测试,所以我会把它放到 想法堆 中。但我的意思是,CSS 中有一些专门为了性能而设计的特性,让我感到困惑,我希望我能够更全面地理解它们,因为它们似乎非常重要。

以 Johan Isaksson 的 “如何用一行 CSS 代码将 Google 的数据网格滚动速度提高 10 倍” 为例。滚动性能提高 10 倍是一件大事!你知道他们是怎么修复的吗?

[…] 当我浏览“顶级链接网站”页面时,我注意到滚动存在明显的滞后。当选择显示更大的数据集(500 行)而不是默认的 10 个结果时,就会出现这种情况。

[…]

那么,我做了什么?我只是在 Elements 面板上的 <table> 上添加了一行 CSS 代码,指定它不会影响页面上其他元素的布局或样式。

table {
  contain: strict; 
}

contain 属性 是另一个我“有点”理解的属性,但我仍然认为它是我的盲点,因为我的大脑不会自动想到我什么时候可以用(或应该用)它。但这是一个问题,因为显然如果我能更好地理解 contain,我构建的界面就不像现在这样高效。

还有一个!content-visibility 属性。我离理解它最近的一次是在观看 Jake 和 Surma 关于它的 视频 之后,他们使用它(以及 contain-intrinsic-size 和一些奇怪的魔数)来极大地加快长页面的速度。但我还没有完全理解的是,我什么时候应该在我的页面上使用它。

这三个功能都是“如果需要就使用”的功能吗?在发现某个东西(例如一个巨大的页面)的性能不佳之后,忽略它们直到发现问题,然后使用它们来尝试解决问题,这样做可以吗?几乎是“直到需要时才使用它们”,否则你就陷入了过早优化的境地。这样做的麻烦在于,除非你在性能最低的设备上积极测试,否则你实际上不会注意到性能不佳。

或者这些功能是“这就是现代 CSS,你应该像对待 padding 一样对待它们”的领域?我有点怀疑情况更像是这样。如果你正在构建一个你知道在某些方面不会改变的元素,那么可能值得“包含”它。如果你正在构建一个你知道在某些方面会改变的元素,那么可能值得向浏览器提供这些信息。如果你正在构建页面的一部分,你知道它始终在页面的下方,那么可能值得避免绘制它。但就我个人而言,我还没有完全理解它,所以无法提供任何可靠的建议。