隐藏/透明元素是否会影响渲染性能?

时间:2017-08-20 13:35:52

标签: javascript html css web-component

所以我有一个我正在写的Polymer应用程序。我已经为装载覆盖层编写了一个非聚合物网络组件,我可以在加载聚合物时以及当应用程序Websocket连接/重新连接时显示。

以下是一些我必须说明我正在做什么的CSS:

  .overlay {
    background: #000;
    bottom: 0;
    height: 100%;
    left: 0;
    opacity: 0;
    pointer-events: none;
    position: fixed;
    right: 0;
    transition: opacity 0.2s;
    top: 0;
    width: 100%;
    z-index: 9999999;
  }

  .overlay[opened] {
    opacity: 0.8;
    pointer-events: auto;
  }

  .loader {
    display: none;
  }

  .overlay[opened] .loader {
    display: block;
  }

现在这个叠加层和我所拥有的基于CSS的加载器动画仅在我真实地加载应用程序时使用,但是如果WebSocket断开连接也会显示它。

我的问题是,出于性能原因,我应该完全从DOM中删除元素并在需要时将其添加回来吗?叠加在不使用时是否完全透明,隐藏加载器动画是否意味着它们对绘图性能没有影响?

注意:我希望尽可能避免“不要微观优化”的答案;)

2 个答案:

答案 0 :(得分:2)

<强> TL; DR:

通常,渲染元素会影响页面性能,当对其进行更改会触发DOM中后续元素的重绘或者在其父级上触发resize时,因为resize会因此而变得昂贵最高可达100次/秒,具体取决于设备。

只要对元素的更改不会在DOM树中的后续元素上触发重绘,就会将其渲染,隐藏在某个不透明元素后面(或在内容上方,opacity:0和{{1}之间并且根本没有显示它是微不足道的。

元素 的更改不会触发除自身 之外的任何内容的重绘,因为它具有pointer-events:none。如果它具有position:fixed或者对它的更改将通过不会在后续兄弟节点上触发重绘的属性(例如position:absolutetransform)进行更改,则情况也是如此。

除非加载器在渲染引擎上非常繁重(很少出现这种情况) - 想想带有3d场景,材质和灯光映射的WebGL加载器 - 在这种情况下,最好不向用户显示时不显示它,差异将是如此之小,真正的挑战是衡量这种差异,性能明智。

事实上,如果对其进行渲染并且仅更改其opacityopacity属性并不总是比切换其pointer-events属性更便宜,我不会感到惊讶,因为每次打开/关闭浏览器时,浏览器都不必从DOM中添加/删除它。但是,真正的问题是:我们如何衡量它?

编辑:实际上,我制作了一个小型测试工具,有10k模态。我在Chrome上的Linux上获得了以下结果:

display

...所以我的假设是正确的:`opacity` average: 110.71340000000076ms | count: 100 `display` average: 155.47145000000017ms | count: 100 整体来说更贵。

display更改大多数在opacity左右,除了少数例外,而110ms更改在删除节点时更快,但在添加时更慢。

随意在不同的浏览器中,在不同的系统上自行测试:

display
$(window).on('load', function () {
  let displayAvg = 0, displayCount = 0,
      opacityAvg = 0, opacityCount = 0;
  for (let i = 0; i < 10000; i++) {
    $('body').append($('<div />', {
      class: 'modal',
      html:'10k &times; modal instances'
    }))
  }
  $(document)
    .on('click', '#display', function () {
      $('.modal').removeClass('opacity');
      let t0 = performance.now();
      $('.modal').toggleClass('display');
      setTimeout(function () {
        let t1 = performance.now();
        displayAvg += (t1 - t0);
        console.log(
          '`display` toggle took ' + 
          (t1 - t0) +
          'ms \n`display` average: ' + 
          (displayAvg / ++displayCount) + 
          'ms | count: ' + 
          displayCount
        );
      })
    })
    .on('click', '#opacity', function () {
      $('.modal').removeClass('display');
      let t0 = performance.now();
      $('.modal').toggleClass('opacity');
      setTimeout(function () {
        let t1 = performance.now();
        opacityAvg += (t1 - t0);
        console.log(
          '`opacity` + `pointer-events` toggle took ' + 
          (t1 - t0) + 
          'ms \n`opacity` average: ' + 
          (opacityAvg / ++opacityCount) + 
          'ms | count: ' + 
          opacityCount
        );
      });
    })
});
body {
  margin: 0;
}
.buttons-wrapper {
  position: relative;
  z-index: 1;
  margin-top: 3rem;
}
.modal {
  height: 100vh;
  width: 100vw;
  position: fixed;
  top: 0;
  left: 0;
  padding: 1rem;
}
.modal.display {
  display: none;
}
.modal.opacity {
  opacity: 0;
  pointer-events: none;
}
.as-console-wrapper {
  z-index: 2;
}

但这个平均值是10k元素。将它除以10k,它几乎没有任何区别:我们的谈话时间不到0.45%。

答案 1 :(得分:0)

如果元素具有'Animation'属性进行动画处理且其持续时间是无限的,浏览器将不断重绘网站,这将影响网站性能并降低FPS。

但是隐藏具有诸如 Opacity:0; 之类的属性的元素不会成功,因为元素仍在CSSOM渲染树队列中。

Visibility:hidden; display:none; 应该可以做到这一点,因为CSSOM构造浏览器不会呈现诸如 display:none之类的隐藏元素;和可见性:隐藏