前端优化-渲染优化三-管道-css

web前端优化–管道–css

平时我们碰到的问题常常是由javascript触发的,但是并不一定是javascript的问题。

这是管道优化系列的css篇。管道的概念见 渲染优化 ,这里详细的介绍了浏览器如何渲染一个帧。管道是帧渲染中的一部分。

选择器匹配和BEM

除了考虑元素数量之外,还要考虑选择器匹配。选择器匹配就是确认某部分样式是否应用到指定dom元素的过程。可能像这样

```, 也可能像 ```.box:nth-child(3)```这样的复杂css。之所以说它复杂是因为它要先找到所有的```.box```,再确定它是父元素的第三个子元素,要知道 cssom是树结构,寻找过程中可能需要上上下下的遍历这个树。可能在页面结构比较简单的时候并没有什么关系,浏览器可能1ms就完成了匹配。如果你的页面上有成千上万个元素,建议试试[BEM](https://en.bem.info/methodology/css/)。这是一种css命名规范,意在提供更加模块化、可重复使用、更易阅读的css,也能一定程度的提高性能。大多数现代浏览器中, 类选择器一般是最快速的。刚刚的例子或者可以写成 .box--three
1
2
3
4
5
6
7
8
9
10
``` html
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
.box{
color:green;
}
.box:nth-child(3) {
color:#ff5050;
}

强制同步布局

再来看一下渲染管道,保持这一顺序重要。

javascript ==> style ==> layout ==> paint ==> composite

举个例子:

1
2
3
4
5
6
let doms = document.querySelector('p')
let block = document.getElementById('block')
for (var i = 0; i < doms.length; i++) {
let bWidth = block.offsetWidth
doms[i].style.width = bWidth + 'px'
}

这段代码可能潜藏着一些危险。

  1. 第一次循环的时候很正常, 获取了block.offsetWidth.set doms[i].style.width
  2. 第二次循环,在获取block.offsetWidth的时候,浏览器发现 doms[i].style.width已经被更改,就会强制重新计算布局。因为它可能造成布局变化。
  3. 第三次循环,同第二次
  4. ….直到结束

问题发生了,Layout行为跑到了Javascript里,管道执行顺序出了问题。我们的页面可能会发生肉眼可见的布局抖动。我们应该注意时刻保持管道执行顺序。如何(不)在 WebKit 中触发布局

最后

看来 对于性能而言,重要的是管道。而不是javascript或者css。用javascript实现的动画、用css实现的动画并不重要。或者我们更需要关心是否触发了强制布局同步,是否消耗了大量的性能参与了layout、paint。csstriggers.com详细的列出了每个css会造成layout还是paint还是仅仅composite.