提高CSS的性能与易维护性的技巧

1,092 阅读8分钟

什么是可维护性?

通常指代码的易理解程度以及易于修改扩展的程度。好的代码一定是易于开发人员阅读理解的,并且对扩展开放对修改关闭。这需要一定的开发经验以及对业务的抽象概括能力。

什么是性能?

代码的性能指:代码的传输加载速度,执行速度。在CSS方面具体指的就是:CSS代码体积,CSS选择器的匹配效率,样式属性的渲染速度等。

一、提高CSS可维护性技巧

1.CSS文件的合理组织

对于较为复杂的项目可以将你的CSS文件分为下面几类:

reset.css文件//重置不同浏览器默认样式
global.css文件//项目全局样式如清除浮动、文本省略
global_variable.scss文件//项目全局CSS变量如颜色、字体、间距
mixins.scss文件//项目全局用到的混合样式用于抽象出class样式中共同的样式属性
xxx_mixins.scss文件//项目局部用到的混合样式
xxx.css文件//具体的页面或组件样式
layout.css文件//页面布局基本样式
header.css文件//页面布局部分样式
nav.css文件//页面布局部分样式
main.css文件//页面布局部分样式
footer.css文件//页面布局部分样式
theme.scss文件//切换项目主题/皮肤样式

2.推荐的class命名及CSS代码组织方式

  1. 首先要知道浏览器对于classid名称的大小写是敏感的。
  2. id一般用于js选择操作DOM元素 尽量不用id作为样式选择器
  3. 推荐全部使用小写并用“-”连接,不要使用只有自己能看懂得缩写。
  4. 对于> +这样的选择器应左右使用空格隔开,对于“”选择器最好换行。
  5. 对于页面CSS文件中的代码,要给予文件注释型说明,如果文件过长,应建立注释型索引目录。最好分段注释说明每块代码的作用位置及意义,以便后期进行局部修改或抽离封装。对于奇特的样式属性写法可以给予注释说明。

3.推荐的CSS属性样式书写方式

3.1 CSS属性的书写顺序

相关的属性声明应当归为一组,并按照(布局类属性->盒模型属性->文本类属性->修饰类属性)顺序排列:

布局属性处在第一位,是因为它可以使一个元素脱离正常文本流,并且覆盖盒模型相关的样式。盒模型紧跟其后,因为它决定了一个组件的大小和位置。其他属性只在组件内部起作用或者不会对前面两种情况的结果产生影响,所以它们排在后面。常见的属性分类如下:

布局类属性: position / top / right / bottom / left / float / display / overflow
盒模型属性: border / margin / padding / width / height
文本类属性: font / line-height / text-align / word-wrap
修饰类属性: background / color / transition / list-style

3.2 CSS属性的缩写
  1. 属性值为0的属性,应直接用0表示而无需单位。
  2. 对于有多个值的属性,超过2个值应该使用缩写。
  3. 对于带有小数的属性值,可以省略小数点前面的0。
  4. 慎用!important
3.3 CSS属性的继承特性

应该合理使用CSS属性自身的继承特性,而不是重复书写那些属性:比如font,text,color相关属性的值是默认可以继承的。

二、提高CSS性能技巧

1.提高CSS文件加载速度

  1. 善用缓存:只有版本更新时才去改变文件名从而刷新缓存。
  2. 优先使用mixins混合器:
    同样是对一段样式属性的封装,mixins与class之间的区别是什么呢?
    首先最本质的区别就是类名是在html文件中应用的,而混合器是在样式表中应用的。 其次类名具有更主观的语义化含义及作用描述,而不仅仅是一种客观的展示性的描述:用来描述html元素的含义而不是html元素的外观。而另一方面,混合器是客观展示性的描述,用来描述一条CSS规则应用之后会产生怎样的效果。混合器主要用于展示性样式的重用,而类名用于语义化样式的重用存。因此mixins是比class更细粒度的代码复用,我们应该注意的CSS代码复用优先级(复用scss变量>复用mixins混合器>复用class<复公共CSS文件)其复用粒度逐渐增大。

2.提高CSS选择器的匹配效率

2.1 CSS选择器性能排行(从高到低)
1.id选择器(#myid2.类选择器(.myclassname3.标签选择器(div,h1,p4.相邻选择器(h1+p5.子选择器(ul > li6.后代选择器(li a7.通配符选择器(*)
8.属性选择器(a[rel="external"]9.伪类选择器(a:hover,li:nth-child
2.2 CSS选择器使用原则
  1. class选择器用于一个或一类元素的选择
  2. 属性选择器用于选择具有特殊或共同属性的元素
  3. 派生选择器尽量层级控制3层以内,结合用元素选择器使用时要保证其结构的固定性即此处未来变动可能性不大
  4. 尽量不使用派生选择器,如果使用则尽量用>子级选择器而不是后代选择器或直接用单个class选择器代替
2.2 CSS选择器选择器优先级/权重

首先大家都知道这些优先级:important>内联 > ID选择器 > 类选择器 > 标签选择器。

假设优先级是由 A 、B、C、D 的值来决定的,其中它们的值计算规则如下:
如果存在内联样式,那么 A = 1, 否则 A = 0;
B 的值等于 ID选择器 出现的次数;
C 的值等于 类选择器 和 属性选择器 和 伪类 出现的总次数;
D 的值等于 标签选择器 和 伪元素 出现的总次数 。

eg:#cav-global > ul > li > a.nav-link
套用上面的算法,依次求出 A B C D 的值:
因为没有内联样式 ,所以 A = 0;
ID选择器总共出现了1次, B = 1;
类选择器出现了1次, 属性选择器出现了0次,伪类选择器出现0次,所以 C = (1 + 0 + 0) = 1;
标签选择器出现了3次, 伪元素出现了0次,所以 D = (3 + 0) = 3;
上面算出的A 、 B、C、D 可以简记作:(0, 1, 1, 3)。

eg: #nav .selected > a:hover // (0, 1, 2, 1)
eg: html body #nav .selected > a:hover // (0, 1, 2, 3)
比较规则: 从左往右依次进行比较 ,较大者胜出,如果相等,则继续往右移动一位进行比较 。如果4位全部相等,则以最后定义的选择器为准。

例外:max-width 可以超越 width!important。但是,这实际上不是优先级的问题,因为优先级是比较相同属性的,而 max-width 和 width 是属性间的约束。

3.提高样式的渲染速度

3.1 减少回流、重绘的次数
是什么回流?

当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。

是什么重绘?

在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘。这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。

注意:回流必将引起重绘,而重绘不一定会引起回流。

回流重绘何时发生?

当页面布局和几何属性改变时就需要回流,下述情况可能会发生浏览器回流:
1、添加或者删除可见的DOM元素;
2、元素位置改变;
3、元素尺寸改变——边距、填充、边框、宽度和高度;
4、内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;
5、页面渲染初始化;
6、浏览器窗口尺寸改变——resize事件发生时;

减少回流重绘的一些技巧:

1.用position:absolute脱离文档流,独立到一个图层;
2.不要一条条的修改DOM样式,而是写成一个class ,修改DOM的className;
3.对于复杂的变化,把DOM元素设置display:none,修改完再显示;
4.合理使用table,因为table部分的改变会引起整个table的重绘。而DIV一般只会影响所改变位置之后的,不会影响之前的;
5.缓存会触发回流的样式属性值,比如:offsetWidth, offsetHeight, clientWidth,clientHeight,不要再循环里进行读写;
6.对于频繁变化的元素应该为其加一个 transform 属性;
7.牺牲平滑度换取速度:每次移动1像素改为每次移动N像素;

3.2 充分利用CSS3的GPU硬件加速特性

常见的触发硬件加速的CSS属性:transform、opacity、filter、Will-change。
(1) 用transform替换top left width height等属性;
(2) 用opacity替换visibility hidden等属性;
(3) 用filter替换box-shadow opacity等属性;
(3) 用Will-change:要开启加速的属性手动开启硬件加速功能,will-change 的设计初衷是作为最后的优化手段,所以最佳实践是当元素变化之前和之后通过脚本来切换 will-change 的值;