CSS性能优化(CSS选择器解析过程)

今天看书突然看到CSS竟然还有性能优化?!看了看好像还挺有用的,遂记之。

CSS性能优化技巧:

属性缩写
语法压缩
图片压缩
选择器优化
CSS模块化
压缩工具
CSS Sprite
性能评估

其中属性缩写和语法压缩没什么好介绍的,属性缩写就是尽可能的将多条属性写成一条,例如:

border-width: 1px;
border-style: solid;
border-color: pink;
可缩写为:border: 1px solid pink;
类似的还有margin, padding, font, background等属性。

而语法压缩就是根据语法格式,规则,把能省掉的都省掉,例如空白符、结尾分号、url()中的引号、0.5px中的0、利用继承合并公共属性等......不过我觉得这不用我们自己做,因为有专门的压缩工具,而且自己省略的话会影响一定的语义,不太好。这两点都是通过减少一定的不必要字符来达到一定的优化,可见其优化效果可能并不是很大。

CSS压缩网站:csscompressor.com 和YUI compressor。其他工具webpack, gulp等 都可以用来打包将要上线的CSS代码,减小体积。

图片压缩顾名思义,也不必多谈,只需记住:

JPEG格式图片主要用来展示色彩丰富的复杂高品质图片,不支持透明;
PNG是一种无损格式,体积小,可以无损压缩保证页面打开速度,支持透明;
GIF效果较差,用作动画。
JPEG压缩网站:jpegmini.com
PNG压缩网站:tinypng.com

下面主要讲讲选择器优化:

当知道浏览器对选择器解析的规则是:从右到左解析(或者说 逆向匹配)的时候,我是懵逼的......因为我之前写选择器都是写很长,很多层选择器,想以此来提高效率,看来路完全走反了_(:ᗤ」ㄥ)_。

那么什么是从右到左解析的?看看下面这个例子就知道了:

#column .content div{color: red;}
浏览器的解析顺序是:
1、查找所有div元素;
2、然后查找该div是否存在具有.content的父元素;
3、最后在已经匹配的父元素中继续向上查找祖先元素是否含有id为column的元素。

那么问题来了,浏览器为什么会采用这种貌似反常规式的解析方式呢?这就要从DOM和CSSOM树的建立和解析开始说起了:

CSS选择器解析:

以下引自:http://www.cnblogs.com/aaronjs/p/3300797.html

  • HTML 经过解析生成 DOM Tree(这个我们比较熟悉);而在 CSS 解析完毕后,需要将解析的结果与 DOM Tree 的内容一起进行分析建立一棵 Render Tree,最终用来进行绘图。Render Tree 中的元素(WebKit 中称为「renderers」,Firefox 下为「frames」)与 DOM 元素相对应,但非一一对应:一个 DOM 元素可能会对应多个 renderer,如文本折行后,不同的「行」会成为 render tree 种不同的 renderer。也有的 DOM 元素被 Render Tree 完全无视,比如 display:none 的元素。
  • 在建立 Render Tree 时(WebKit 中的「Attachment」过程),浏览器就要为每个 DOM Tree 中的元素根据 CSS 的解析结果(Style Rules)来确定生成怎样的 renderer。对于每个 DOM 元素,必须在所有 Style Rules 中找到符合的 selector 并将对应的规则进行合并。选择器的「解析」实际是在这里执行的,在遍历 DOM Tree 时,从 Style Rules 中去寻找对应的 selector。
  • 因为所有样式规则可能数量很大,而且绝大多数不会匹配到当前的 DOM 元素(因为数量很大所以一般会建立规则索引树),所以有一个快速的方法来判断「这个 selector 不匹配当前元素」就是极其重要的。
  • 如果正向解析,例如「div div p em」,我们首先就要检查当前元素到 html 的整条路径,找到最上层的 div,再往下找,如果遇到不匹配就必须回到最上层那个 div,往下再去匹配选择器中的第一个 div,回溯若干次才能确定匹配与否,效率很低。
  • 逆向匹配则不同,如果当前的 DOM 元素是 div,而不是 selector 最后的 em,那只要一步就能排除。只有在匹配时,才会不断向上找父节点进行验证。
  • 但因为匹配的情况远远低于不匹配的情况,所以逆向匹配带来的优势是巨大的。同时我们也能够看出,在选择器结尾加上「*」就大大降低了这种优势,这也就是很多优化原则提到的尽量避免在选择器末尾添加通配符的原因。

我的理解就是,CSSOM Tree在和DOM Tree一起建立Render Tree时,先遍历DOM Tree的各个节点(从上往下,从父到子),通过节点位置再去查找CSSOM中对应的选择器规则,即从CSSOM Tree的叶子节点开始筛选,这样从右到左解析选择器就避免了从左到右解析的每次都要检查整条DOM路径,如果不对还要进行多次回溯的局面。(其实就是上面的话orz)

webkit渲染过程

 

延伸阅读:How Browsers Works 深度好文,浏览器工作原理剖析

       《css加载会造成阻塞吗》 通俗易懂,一定程度上借鉴了↑

这样看来,选择器的书写很关键,最右边的选择器影响最大,很关键!在书写选择器时也有以下的几个技巧:

  1. 不建议通配选择符;
  2. 不要在id选择器前加元素名(完全没有必要),不建议在class前加元素名(除非很有必要);
  3. 选择器最好不要超过三层,最右边的选择器尽可能精确;
  4. 子选择器比后代选择器好用,因为后代选择器匹配量大,不精确。(这条好像无所谓啊,该用还得用...)

CSS Sprite就不用多说了,雪碧图人尽皆知。

至于CSS模块化和性能评估书上也没有讲,而且跟SASS预处理器有关,好像有点复杂,先坑着吧,吃饭去了,有空再填。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值