前言
对于一个网站而言,性能至关重要,关系到用户体验效果和用户留存率。CSS作为页面渲染和内容展现的重要环节,是影响用户体验的第一道关卡。因此,CSS相关的性能优化不容忽视。在做优化之前,先理解以下几个点
- 1.关键渲染路径(Critical Rendering Path):关键渲染路径是浏览器将 HTML、CSS、JavaScript 转换为在屏幕上呈现的像素内容所经历的一系列步骤。
- 2.重绘(Repaint):当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility 等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
- 3.重排(Reflow):当渲染树(Render Tree)中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
- 4.CSS选择器匹配规则:从右向左匹配。原因是如果通过最右的选择器能准确匹配到对应的DOM节点,那么就停止查询,开始绘制;否则就继续往左查询,直到能准确匹配为止。这个匹配规则大大提升了渲染效率
下面根据以上几点来做对应的性能优化。
优化关键渲染路径
- 1.减小CSS文件体积:压缩CSS文件,减少文件空白节点;封装公共代码,减少代码量,提高维护性;利用CSS部分代码能够继承的特性减少代码量
- 2.异步加载CSS文件:对于不是必须第一时间加载的CSS文件使用异步加载
<link rel="preload" href="mystyles.css" as="style"> - 3.预先加载CSS文件:在浏览器空闲的时间偷偷预先加载
<link rel="prefetch" href="url"> - 4.避免使用@import引入CSS文件:无法和HTML并行加载,页面加载完毕后才被加载;多个@import会导致下载顺序紊乱
- 5.避免使用CSS表达式:例如
calc() - 6.必要时可以使用内联样式,通过减少HTTP请求来提高页面渲染效率
优化重绘
- 1.尽量使用 transition 和 animation来实现CSS动画,而不是JS实现动画(运行在主线程对动画的流畅度有影响)
- 2.动画尽量多用transfrom 和 opacity
- 3.translateZ/translate3d 开启硬件加速
- 4.规范CSS属性书写顺序,避免重复绘制,比如如下代码
/* bad */
span {
/* 开始绘制width和height无效,当display为block会重新触发绘制 */
width: 200px;
height: 200px;
background: red;
display: block;
}
.box {
width: 50%;
height: 100px;
background: blue;
position: absolute;
}
动画测试小技巧:借助Chrome的开发者工具进行CPU降速,然后再进行相关的测试,降速方法如下图所示
优化重排
重排比重绘对页面性能的影响更大,会导致页面重排的操作有如下:
1.页面首次渲染
2.浏览器窗口大小发生改变
3.元素尺寸或位置发生改变元素内容变化(文字数量或图片大小等等)
4.元素字体大小变化
5.添加或者删除可见的 DOM 元素
6.激活 CSS 伪类(例如:hover)
另外,我们可以通过CssTriggers查询哪些属性会触发重排与重绘。
因此,针对页面重排,我们可以做如下优化
- 1.避免使用 table 布局
- 2.避免频繁改变font-size和font-family
- 3.避免频繁改变元素的内外边距
- 4.避免频繁通过JS改变CSS类
- 5.避免频繁激活CSS伪类
- 6.将动画效果应用到 position 属性为 absolute 或 fixed 的元素上
- 7.使用有更好重排性能的flex布局
优化选择器匹配
- 1.避免使用通配符
*和属性选择器:需要匹配元素多,匹配效率低 - 2.避免嵌套过多、过于复杂的选择器:建议选择器的嵌套不超过三层,其实这涉及到了HTML结构代码的层级和class、id的命名技巧。有兴趣的可以去了解下CSS的设计模式。
<!-- bad -->
<div class='box'>
<div class='header'>
<p class='text'>文本</p>
</div>
</div>
<style>
.box .header .text {}
</style>
<!-- good -->
<div class='box'>
<div class='box-header'>
<p class='box-header-text'>文本</p>
</div>
</div>
<style>
.box-header-text {}
</style>