CSS选择器损耗到底来自哪里呢?
CSS选择器对性能的影响源于浏览器匹配选择器和文档元素时所消耗的时间,所以优化选择器的原则是应尽量避免使用消耗更多匹配时间的选择器。而在这之前我们需要了解CSS选择器匹配的机制, 如子选择器规则:
#header > a{font-weight:blod;}
CSS选择器是从右到左进行规则匹配,例子中看似高效的选择器在实际中的匹配开销是很高的,浏览器必须遍历页面中所有的 a 元素并且确定其父元素的 id 是否为 header 。
那么,如何减少 CSS 选择器性能损耗?
一般认为,CSS选择器的执行效率从高到低如下:
/*1.id选择器(#myid)
2.类选择器(.myclassname)
3.标签选择器(div,h1,p)
4.相邻选择器(h1+p)
5.子选择器(ul < li)
6.后代选择器(li a)
7.通配符选择器(*)
8.属性选择器(a[rel="external"])
9.伪类选择器(a:hover, li:nth-child)*/
根据以上「选择器匹配」与「选择器执行效率」原则,我们可以通过避免不恰当的使用,提升 CSS 选择器性能。
1、避免使用通用选择器
.content * {color: red;}
浏览器匹配文档中所有的元素后分别向上逐级匹配 class 为 content 的元素,直到文档的根节点。因此其匹配开销是非常大的,所以应避免使用关键选择器是通配选择器的情况。
2、避免使用标签或 class 选择器限制 id 选择器
/*BAD*/
button #backButton {…}
/*BAD*/
.menu-left #newMenuIcon {…}
/*GOOD*/
#backButton {…}
/*GOOD*/
#newMenuIcon {…}
3、避免使用标签限制 class 选择器\
/*BAD*/
treecell.indented {…}
/*GOOD*/
.treecell-indented {…}
/*BEST*/
.hierarchy-deep {…}
4、避免使用多层标签选择器。使用 class 选择器替换,减少css查找
/*BAD*/
treeitem[mailfolder="true"] > treerow > treecell {…}
/*GOOD*/
.treecell-mailfolder {…}
5、避免使用子选择器
/*BAD*/
treehead treerow treecell {…}
BETTER, BUT STILL BAD
treehead > treerow > treecell {…}
/*GOOD*/
.treecell-header {…}
6、使用继承
/*BAD*/
#bookmarkMenuItem > .menu-left{ list-style-image:url(blah) }
/*GOOD*/
#bookmarkMenuItem { list-style-image: url(blah) }
作为一名前端开发人员,必须具有「提升 CSS 选择器性能」的意识,但实际应用中,是否需要完全贯彻这些原则呢?这是一个探索「追求高性能」与「可维护性」两者平衡的问题,具体应该怎么做要视情况而定。