css也需要性能优化
# css也需要性能优化
我们都知道对于网站来说,性能至关重要,CSS作为页面渲染和内容展现的重要环节,影响着用户对整个网站的第一体验。因此,与其相关的性能优化是不容忽视的。
# 一、选择器优化
CSS选择器的匹配是从右向左进行的
CSS中更多的选择器是不会匹配的,所以在考虑性能问题时,需要考虑的是如何在选择器不匹配时提升效率。从右向左匹配就是为了达成这一目的的,通过这一策略能够使得CSS选择器在不匹配的时候效率更高。这样想来,在匹配时多耗费一些性能也能够想的通了。
比如
<div class="container">
<p class="special-name"> name </p>
</div>
.container .special-name{
color:red
}
2
3
4
5
6
7
如果从左往右匹配,那么container
和special-name
两个类都需要进行匹配。
如果从左向右,那么只需要匹配到special-name
就能确定这个标签,不需要再对container
进行匹配了
这一策略导致了不同种类的选择器之间的性能也存在差异。
<div class="container">
<p class="text">内容</p>
</div>
方法1
.container p{
color:red
}
方法2
.container .text{
color:red
}
2
3
4
5
6
7
8
9
10
11
12
显然,方法1的p标签匹配范围更广更耗费性能
不过现代浏览器在这一方面做了很多优化,不同选择器的性能差别并不明显。
我们在使用选择器时,只需要记住以下几点。
保持简单,不要使用嵌套过多过于复杂的选择器。
通配符和属性选择器效率最低,需要匹配的元素最多,尽量避免使用。
尽量不要出现如下这种css覆盖情况
# 二. 优化重排与重绘
在网站的使用过程中,某些操作会导致样式的改变,这时浏览器需要检测这些改变并重新渲染,其中有些操作所耗费的性能更多。我们都知道,当FPS为60时,用户使用网站时才会感到流畅。这也就是说,我们需要在16.67ms内完成每次渲染相关的所有操作,所以我们要尽量减少耗费更多的操作。
有关重排和重绘可以参考我这篇文章重排和重绘 (opens new window)
# 1.减少重排
重排会导致浏览器重新计算整个文档,重新构建渲染树,这一过程会降低浏览器的渲染速度。如下所示,有很多操作会触发重排,我们应该避免频繁触发这些操作。
- 改变
font-size
和font-family
- 改变元素的内外边距
- 通过JS改变CSS类
- 通过JS获取DOM元素的位置相关属性(如width/height/left等)
- CSS伪类激活
- 滚动滚动条或者改变窗口大小
值得一提的是,某些CSS属性具有更好的重排性能。如使用Flex
时,比使用inline-block
和float
时重排更快,所以在布局时可以优先考虑Flex
。
# 2.减少重绘
当元素的外观(如color,background,visibility等属性)发生改变时,会触发重绘。在网站的使用过程中,重绘是无法避免的。不过,浏览器对此做了优化,它会将多次的重排、重绘操作合并为一次执行。不过我们仍需要避免不必要的重绘,如页面滚动时触发的hover事件,可以在滚动的时候禁用hover事件,这样页面在滚动时会更加流畅。
此外,我们编写的CSS中动画相关的代码越来越多,我们已经习惯于使用动画来提升用户体验。我们在编写动画时,也应当参考上述内容,减少重绘重排的触发。
除此之外我们还可以通过硬件加速来提升动画性能,本文不对此展开详细介绍,感兴趣的小伙伴可以点击链接进行查看。
如果需要在移动端访问的,最好将速度限制更低,因为移动端的性能往往更差。
# 三、首屏优化
性能优化中有一个重要的指标——首次有效绘制(First Meaningful Paint,简称FMP)即指页面的首要内容(primary content)出现在屏幕上的时间。这一指标影响用户看到页面前所需等待的时间,而**内联首屏关键CSS(即Critical CSS,可以称之为首屏关键CSS)**能减少这一时间。
大家应该都习惯于通过link标签引用外部CSS文件。但需要知道的是,将CSS直接内联到HTML文档中能使CSS更快速地下载。而使用外部CSS文件时,需要在HTML文档下载完成后才知道所要引用的CSS文件,然后才下载它们。所以说,内联CSS能够使浏览器开始页面渲染的时间提前,因为在HTML下载完成之后就能渲染了。
既然内联CSS能够使页面渲染的开始时间提前,那么是否可以内联所有的CSS呢?答案显然是否定的,这种方式并不适用于内联较大的CSS文件。因为初始拥塞窗口 (opens new window)3存在限制(TCP相关概念,通常是 14.6kB,压缩后大小),如果内联CSS后的文件超出了这一限制,系统就需要在服务器和浏览器之间进行更多次的往返,这样并不能提前页面渲染时间。因此,我们应当只将渲染首屏内容所需的关键CSS内联到HTML中。
既然已经知道内联首屏关键CSS能够优化性能了,那下一步就是如何确定首屏关键CSS了。显然,我们不需要手动确定哪些内容是首屏关键CSS。Github上有一个项目Critical CSS,可以将属于首屏的关键样式提取出来,大家可以看一下该项目,结合自己的构建工具进行使用。当然为了保证正确,大家最好再亲自确认下提取出的内容是否有缺失。
不过内联CSS有一个缺点,内联之后的CSS不会进行缓存,每次都会重新下载(原因可查看前端打包文件的缓存机制 (opens new window))。不过如上所说,如果我们将内联后的文件大小控制在了14.6kb以内,这并不是大问题。
# 四、文件压缩
文件的大小会直接影响浏览器的加载速度,这一点在网络较差时表现地尤为明显。
相信大家都早已习惯对CSS进行压缩,现在的构建工具,如webpack、gulp/grunt、rollup等也都支持CSS压缩功能。
压缩后的文件能够明显减小,可以大大降低了浏览器的加载时间。
除了压缩文件,服务端也可以开启GZIP压缩文本,让网络传输时间进一步降低