CSS压缩
CSS
压缩并不是什么高端的姿势,但却很有用,其原理很简单,就是把我们CSS
中没用的空白符等删去,达到缩减字符个数的目的。
我们有这样一段CSS
脚本:
.test {
background-color:#ffffff;
background-image:url(a.jpg);
}
经过压缩后会变成这样
.test { background-color:#fff; background-image:url(a.jpg)}
Gzip压缩
Gzip
是一种流行的文件压缩算法,现在的应用十分广泛,尤其是在Linux
平台,这个不止是对CSS
,当应用Gzip
压缩到一个纯文本文件时,效果是非常明显的,大约可以减少70%
以上的文件大小(这取决于文件中的内容)。
Web服务器处理HTTP压缩的过程如下:
1. Web服务器接收到浏览器的HTTP请求后,检查浏览器是否支持HTTP压缩(Accept-Encoding 信息);
2. 如果浏览器支持HTTP压缩,Web服务器检查请求文件的后缀名;
3. 如果请求文件是HTML、CSS等静态文件,Web服务器到压缩缓冲目录中检查是否已经存在请求文件的最新压缩文件;
4. 如果请求文件的压缩文件不存在,Web服务器向浏览器返回未压缩的请求文件,并在压缩缓冲目录中存放请求文件的压缩文件;
5. 如果请求文件的最新压缩文件已经存在,则直接返回请求文件的压缩文件;
6. 如果请求文件是动态文件,Web服务器动态压缩内容并返回浏览器,压缩内容不存放到压缩缓存目录中。
利用继承
CSS
的继承机制也可以帮我们再一定程度上缩减字节数,我们知道CSS
有很多属性是可以继承的即在父容器设置了默写属性,子容器会默认也使用这些属性,因此如果我们希望全文字体尺寸是14px,大可不必为每个容器设置,只需要在body
上设置就可以了。应用这个技巧,把CSS
属性在可能的情况下提到父容器是可以帮我们节省CSS
字节的,顺便说一下哪些属性可以继承。
所有元素可继承:visibility和cursor
内联元素和块元素可继承:letter-spacing、word-spacing、white-space、line-height、color、font、 font-family、font-size、font-style、font-variant、font-weight、text- decoration、text-transform、direction
块状元素可继承:text-indent和text-align
列表元素可继承:list-style、list-style-type、list-style-position、list-style-image
表格元素可继承:border-collapse
不可继承的:display、margin、border、padding、background、height、min-height、max- height、width、min-width、max-width、overflow、position、left、right、top、 bottom、z-index、float、clear、table-layout、vertical-align、page-break-after、 page-bread-before和unicode-bidi
css 选择器
#yy > li { font-weight: bold }
按照我们惯常的理解,编译器应该是先查找id
为yy
的节点,然后在他的所有直接子节点中查找类型(tag
)为li
的节点,将font-weight
属性应用到这些节点上。
但是,不幸的是,恰恰相反,浏览器是从右往左
来分析 class
的,它的匹配规则是从右向左来进行匹配的。这里,浏览器首先会查找页面上所有的li
节点,然后再去做进一步的判断:如果它的父节点的id
为yy
,则匹配成功。
由此可知,CSS
选择器的匹配远比我们想象的要慢的多,CSS
的性能问题不容忽视。
#yy li {font-weight: bold}
这个效率比之前的child selector
效率更慢,而且要慢很多。浏览器先遍历所有的li
节点,然后步步上溯其父节点,直到 DOM
结构的根节点(document
),如果有某个节点的 id
为yy
,则匹配成功,否则继续查找下一个li
节点。
不要用标签或 class 来限制 ID 规则
这个应该是个常识,但很多同学都会误用,写出#test.info
或者div#test
这样的选择器,这个只能说是画蛇添足,id
已经可以唯一而且最快的定位一个元素了。
不要用标签名限制 class 规则
这个估计被误用的更多,如div.info
这样的写法,其实我们可以直接写为.info
,从右到左解析的原因可以知道为什么其低效,如果直接使用class
不能达到目的,一般情况下应该是class
设计的有问题,CSS
需要重构了。
尽量使用最具体的类别、避免后代选择器、属于标签类别的规则永远不要包含子选择器
这三条规则是想通的,因为从左到右解析关系,在CSS
选择器中后代选择器非但没有帮我们加快CSS
查找,反而后代选择器是 CSS
中耗费最昂贵的选择器。 它的耗费是极其昂贵的—特别是当选择器在标签或通用类别中,能免则免。
优化回流和重绘
回流
浏览器为了重新渲染部分或整个页面,重新计算页面元素位置和几何结构的进程叫做reflow
。回流会导致浏览器重新计算整个文档,重新构建渲染树,这一过程会减低浏览器的渲染速度。
什么时候会导致reflow发生呢?
- 改变窗口大小
- 改变文字大小
- 添加,删除样式表
- 内容的改变(用户在输入框中写入内容也会)
- 激活伪类,如:
hover
- 操作
class
属性 - 脚本操作
DOM
- 计算
offsetWidth
和offsetHeight
- 设置
style
属性
优化回流
- 尽可能限制
reflow
的影响范围,尽可能在低层级的DOM
节点上通过父元素去影响子元素不好。 - 避免设置大量的
style
属性,因为通过设置style
属性改变结点样式的话,每一次设置都会触发一次reflow
,所以最好是使用class
属性。 - 实现元素的动画,它的
position
属性,最好是设为absoulte
或fixed
,这样不会影响其他元素的布局。 - 动画实现的速度的选择。比如实现一个动画,以1个像素为单位移动这样最平滑,但是
reflow
就会过于频繁,大量消耗CPU
资源,如果以3个像素为单位移动则会好很多。 - 不要使用
table
布局,因为table
中某个元素旦触发了reflow
,那么整个table
的元素都会触发reflow
。那么在不得已使用table
的场合,可以设置table-layout:auto
或者是table-layout:fixed
这样可以让table
一行一行的渲染,这种做法也是为了限制reflow
的影响范围。 - 如果
CSS
里面有计算表达式,每次都会重新计算一遍,出发一次reflow
。
重绘
repaint
是在一个元素的外观被改变,但没有改变布局的情况下发生的,如改变了visibility
、outline
、background
等。当repaint
发生时,浏览器会验证DOM
树上所有其他节点的visibility
属性。
启用 GPU 硬件加速
GPU
(Graphics Processing Unit
) 是图像处理器。GPU
硬件加速是指应用 GPU
的图形性能对浏览器中的一些图形操作交给 GPU
来完成,因为 GPU
是专门为处理图形而设计,所以它在速度和能耗上更有效率。
GPU
加速可以不仅应用于3D
,而且也可以应用于2D
。这里, GPU
加速通常包括以下几个部分:Canvas2D
,布局合成(Layout Compositing)
, CSS3转换(transitions)
,CSS3 3D变换(transforms)
,WebGL
和视频(video)
。
/*
* 根据上面的结论
* 将 2d transform 换成 3d
* 就可以强制开启 GPU 加速
* 提高动画性能
*/
div {
transform: translate(10px, 10px);
}
div {
transform: translate3d(10px, 10px, 0);
}
参考文章
浏览器重绘与重排的性能优化
优化CSS重排重绘与浏览器性能
常用CSS优化总结——网络性能与语法性能建议