'显示:无;' 提高或恶化性能?

Meg*_*iae 19 html javascript css performance web-performance

我有一个包含大量垂直滚动和数千个 DOM 元素的页面。为了提高性能,我考虑设置display: none;为视口上方和下方的 div 的内容,即不可见的 div(同时保持高度,显然):

在此处输入图片说明

为了检查我的想法是否有意义,我搜索了 SO 并发现了这个问题。根据评论和接受的答案,最好的策略是什么都不做,因为display: none;触发回流并可能产生相反的效果:

如果您想要避免回流,则将 display 设置为 none 会触发回流,这与您想要的完全相反。不做任何事情不会触发回流。将可见性设置为 hidden 也不会触发回流。然而,没有做任何事情容易得多。

然而,最近一个答案(不幸的是,它看起来更像是一个评论甚至是一个问题)声称这display: none;是 Facebook 等网站当前使用的策略,其中垂直滚动几乎是无限的。

值得一提的是,与 OP 在该问题中的描述不同,我网站中的每个可见 div 都是交互式的:用户可以单击、拖动以及对 div 的内容执行其他操作(我相信这会使浏览器重新绘制页面)。

鉴于所有这些信息,我的问题是:display: none;应用于视口上方/下方的 div 会提高性能还是会降低性能?或者它可能没有效果?

Bek*_*caj 11

元素"display: none"属性从文档流中删除该元素。

动态地重新定义该元素的显示属性从无到任何其他,反之亦然,将再次强制更改文档流。

每次都需要重新计算流级联下的所有元素以进行新的渲染。

因此,是的,将"display: none"属性应用于非零维和自由流动或相对定位的元素,将是一项代价高昂的操作,因此会降低性能

无论如何,情况position: absolute并非如此,从自然和自由文档流中移除的元素可以将其显示属性设置为 none 并返回,而不会触发文档正文上的 e 重排。


现在在您的特定情况下[查看编辑过的图表],当您向下移动/滚动时将“显示:块”带回以下 div不会导致重新流动文档上部的其余部分。因此,您可以安全地将它们显示出来。因此不会影响页面性能。另外display: none尾部的元素,你动起来,因为这将释放更多的显示内存。因此可以提高性能。在 HTML 流的上部和内部添加或删除元素时,情况并非如此! 在此处输入图片说明


Bry*_*son 7

答案是,就像几乎所有事情一样,这取决于。我认为您将不得不自己对其进行基准测试以了解具体情况。以下是运行“平滑度”基准测试的方法,因为对您来说,对速度的感知可能比实际系统性能更重要。

正如其他人所说,display:none将 DOM 留在内存中。通常,渲染是昂贵的部分,但这是基于当事情发生变化时必须渲染的元素数量。如果重绘操作仍然需要检查每个元素,您可能看不到性能的巨大提升。以下是一些需要考虑的其他选项。

使用虚拟 DOM

这就是 React 和 Vue 等框架使用Virtual DOM 的原因。目标是接管浏览器的工作,决定更新什么,只进行较小的更改。

完全添加/删除元素

您可以通过使用Intersection Observer来复制类似的东西来找出视口中/外的内容,并实际从 DOM 中添加/减去,而不是仅仅依赖于display:none单独,因为解析 javascript 通常比大型绘画更有效。

添加 GPU 加速

另一方面,如果GPU 正在接管渲染,绘制可能不会降低性能,但这仅适用于某些设备。您可以通过添加transform: translate3d(0,0,0);强制GPU加速来尝试。

给浏览器提示

您还可以通过使用CSS Will-Change 属性看到改进。输入之一基于视口之外的内容。所以will-change:scroll-position;在元素上。

CSS 内容可见性(最前沿)

W3C 的 CSS 工作组拥有草案形式的CSS 包含模块。这个想法是让开发人员告诉浏览器要绘制什么以及何时绘制。这包括油漆和布局遏制。content-visibility:auto是专为此类问题设计的超级有用的属性。这里有更多的背景

编辑(2021 年 4 月)现在可在 Chrome 85+、Edge (Chromium) 85+ 和 Opera 71+ 中使用。我们仍在等待 Firefox 支持,但 Can I Use 将其覆盖率为 65%。

值得一看,因为我看到演示在性能和 Lighthouse 分数方面产生了巨大的差异。