可见性之间的性能差异:隐藏和显示:无

Posted

技术标签:

【中文标题】可见性之间的性能差异:隐藏和显示:无【英文标题】:Performance differences between visibility:hidden and display:none 【发布时间】:2012-07-30 05:13:09 【问题描述】:

我想在我的 jQuery Backbone.js Web 应用程序中简化一些事情。一种这样的简化是我的菜单和对话框小部件的行为。

之前我在开始时创建了菜单的 div 框并使用 display: none; opacity:0; 隐藏它们。当我需要一个菜单​​时,我将其样式更改为display:block,然后使用jQuery ui 定位实用程序来定位div 框(因为无法定位带有display:none 的元素),完成后,最后将其样式更改为@987654324 @。

现在我想用visibility:hidden 隐藏它们,当我需要一个时,我使用位置实用程序,然后将样式更改为visibility:visible。当我开始使用这种新方法时,我将在整个 Web 应用程序会话中拥有大约 10 个隐藏但占用空间的 div 框,这与之前使用 display:none 隐藏的 div 框形成对比。

我的新方法有什么影响?它是否会在任何方面影响浏览器性能?

【问题讨论】:

【参考方案1】:

我不知道display:nonevisibility:hidden 之间的任何性能差异 - 即使有,对于少至 10 个元素,它也完全可以忽略不计。正如您所说,您主要关心的应该是您是否希望元素保留在文档流中,在这种情况下,visibility 是一个更好的选择,因为它维护了元素的框模型。

【讨论】:

【参考方案2】:

display:none; 元素是not in the render tree all,因此它们在表面上的表现会更好。

我怀疑您是否会因此而遇到任何真正可见的性能问题。如果您需要opacity: 0visibility: hidden 因为它们的功能,那么就使用它们。如果您不需要该功能,请使用display: none;

【讨论】:

+1 - 非常有趣!你知道哪些浏览器有这个渲染树优化吗? @ChrisFrancis 我想说所有但你永远不会知道 IE :D 如果元素有“display: none”,即使 IE 也会忽略它。 虽然第一次可能表现更好,但如果你快速切换display,你就是在自找麻烦。查看其他答案。 如果您有数百个元素,例如平铺地图或游戏,我总是以反向 dom 顺序删除显示属性,以防止容器上的回流!【参考方案3】:

好吧,visibility:none 仍然使用 div 的空间。 因此,您可能会跳过定位部分,因为它的位置已经分配(并由此获得更好的性能)。

但我以某种方式猜测您需要 display:none 方法来在触发“show”事件时正确分配空间。

【讨论】:

【参考方案4】:

visibility: hidden 不会导致文档重排,而display: none 会。

display: nonehtml 引擎将完全忽略该元素及其子元素。引擎不会忽略标有visibility: hidden的元素,它会对元素及其子元素进行所有计算,但不会将元素渲染到视口。

如果需要位置和尺寸属性的值,则必须使用visibility: hidden,并且您必须处理视口中的空白区域,通常通过将该元素包装在另一个宽度和高度为 0 和 'overflow:隐'。

display:none 将从文档的正常流程 中删除该元素,并将该元素及其子元素的位置/高度/宽度的值设置为 0。当元素display 属性更改为除none 之外的其他值时,它会触发完整的文档重新流,这对于大文档来说可能是一个问题——有时在功能有限的硬件上呈现的不是那么大的文档.

display: none 是在视口上隐藏元素时使用的自然且合乎逻辑的解决方案,visibility: hidden 应在需要的地方/时间用作后备。

编辑: 正如@Juan 所指出的,display: none 是您需要向 DOM 树中添加许多元素时的选择。 visibility: hidden 将为添加到树中的每个元素触发重新流,而 display: none 不会。

【讨论】:

这是 display:none 与 visibility:hidden 的真正问题。如果您要向 DOM 添加大量元素,并且将它们隐藏起来,那么您将引发每个元素的重排。另一方面,您可以使用 display:none 添加任意数量的元素,并一次显示所有元素,从而引发一次回流。对性能征税的行为是回流。 @juanlanus 您是否建议添加许多隐藏可见性的元素并将每个元素的可见性更改为可见会引发文档/父元素的重排?或者您是否建议每次由于某种原因在文档上触发重排时这些元素中的每一个都会重排,因为它们是渲染树的一部分? @gaurav5430 将新元素插入 DOM 时触发重排。但是,如果父元素具有 display:none,则添加新元素时不会触发重排。 Visibility:hidden 仍然会触发重排。 为什么元素已经在 DOM / 渲染树中,我们只将可见性从无切换到可见【参考方案5】:

我认为这可能与这个问题有关:CSS Properties: Display vs. Visibility

我只引用有趣的部分:

该元素永远不会从 DOM 层次结构中删除。使用 display:none 时,所有块级显示“样式”都完全“隐藏”,而使用 visibility:hidden;元素本身是隐藏的,但它仍然占据 DOM 中的可视空间。

所以在浏览器性能方面应该没有真正的区别,因为两个版本仍然在 DOM 层次结构中。这些属性仅影响元素相对于 DOM 的显示方式

【讨论】:

仅仅因为一个元素在 DOM 层次结构中并不意味着任何性能。这取决于在屏幕上渲染该元素及其子元素的成本,这可以任意变化。 它们都在 DOM 树中,但 display:none 不会在渲染树中【参考方案6】:

如果您通过 javascript 在可见和不可见状态之间切换,那么可见性:隐藏应该是更好的表现。看到它在可见和隐藏状态下总是占用相同数量的空间,因此每次使它看起来消失时都不会导致其下方元素的回流。对于 display:none ,您将其从文档流中删除,然后当您将其设置为 display:block 时,您将重新渲染它并将该元素下方的所有内容向下推,基本上将所有这些内容再次放置。

但是,如果您正在执行诸如切换按钮按下时的可见状态之类的操作,那么您确实应该使用适合您需求的东西,而不是性能更好的东西,因为在这种情况下性能差异可以忽略不计。当您以每秒 20 次左右的速度使用 dom 制作动画时,您可以担心可见性的性能:隐藏与显示:无。

【讨论】:

如果你提供了来源,我会赞成这个。我知道display:none 会导致回流,而visibility:hidden 不会……直觉上我认为你已经死心了。但是关于 SO 链接到官方文档或更深入的解释的好答案;在没有来源的情况下,我没有足够的背景知识对此主题 +1。 Nicole Sullivan 的这篇文章谈到了它。她通常被认为是 CSS 专家,并帮助构建了 CSSLint。不知道这是否是一个好的来源,但我当然相信她的意见stubbornella.org/content/2009/03/27/… @andywhyisit 来自该资源,它说将显示更改为 None 不会导致回流 .. 但是将可见性更改为 hidden 会导致浏览器中的 1x 回流。 developers.google.com/speed/docs/insights/browser-reflow 对我来说,您的回答似乎是正确的。但是上面提供的资源与之相矛盾。那么哪个是正确的?【参考方案7】:

根据个人经验,我刚刚在一个简单的静态页面上尝试了一个位于“隐藏”按钮下方的表单,visibility: hidden 表现完美,而display: none 导致可点击按钮在点击时略微跳跃,好像它试图显示隐藏按钮一毫秒。

【讨论】:

【参考方案8】:

嗯,display: blockvisibility: hidden 之间的主要性能差异在于,如果您有一个包含 100000 个元素的列表,visibility: hidden 不会让您免于 DOM 挂起,因为它不会删除元素来自 DOM。 visibility: hidden 的行为类似于 opacity: 0 + pointer-events: nonedisplay: none 的行为类似于 Element.remove()

现场示例:https://jsfiddle.net/u2dou58r/10/

【讨论】:

是因为可见性:隐藏元素仍然是布局步骤的一部分,而不是显示:无 @gaurav5430 好吧,从技术上讲,是的。但是说display: none 元素不是布局的一部分并不完全正确,因为它们仍然可以通过JS DOM 方法(如querySelector)来访问。此外,它们仍然会影响nth-child CSS 伪选择器

以上是关于可见性之间的性能差异:隐藏和显示:无的主要内容,如果未能解决你的问题,请参考以下文章

在菜单项的可见性模式之间进行动画处理

Java并发基础并发编程bug源头:可见性原子性和有序性

JavaScript 切换可见性(显示/隐藏)

切换可见性(显示/隐藏)

切换元素 onblur 和 onclick 的可见性

动画可见性模式,GONE 和 VISIBLE