愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

CSS优先级原理分析

使用CSS进行页面开发的时候,经常会遇到有多个规则冲突的情况。这种情况下,理解CSS怎么处理这种冲突,就很有好处

一、特殊性

CSS会对每个规则指定一个特殊性值,其表示为:0, 0, 0, 0四个部分,一个选择器的特殊性值定义如下:
1)对每个ID选择器,加0,1,0,0
2)对每个类选择器、伪类选择器、属性选择器,加0,0,1,0
3)对每个元素选择器、伪元素选择器,加0,0,0,1
4)结合运算符(如>+等)和通配符(*)对特殊性没有贡献,相当于加0,0,0,0
5)继承来的属性没有特殊性,连0特殊性都没有
6)内联样式具有1,0,0,0特殊性
计算一个选择器特殊性的例子如下:

html > body table tr[id="totals"] td ul > li {
    color: maroon
}
li.answer.hot { color: navy }

这个选择器中,包含有0个ID选择器,1个属性选择器([id="totals"]),7个元素选择器(htmlbodytabletrtdulli),所以其特殊性为:
0个, 0个, 1个, 7个 => 0,0,1,7
li.answer.hot { color: navy }包含1个元素选择器(li),2个类选择器(.answer.hot),所以其特殊性为0个,0个,2个,1个 => 0,0,2,1
看起来第一个选择器很复杂,但实际上第二个选择器的特殊性更高,所以是第二个选择器生效了


二、优先级计算规则

CSS解析时会把每个声明块里的声明拆分开来,然后再分别计算。如:

h2 { color: #FFF; background: #888 }

解析时会拆分为:

h2 { color: #FFF }
h2 { background: #888 }

然后CSS的层叠规则为:
1)找出所有相关的规则
2)标明!important的比未标明的先排序,然后再根据特殊性数值大小进行排序
3)按在文档中出现的顺序进行排序,在文档中越后面的排序越靠前,使用@import导入的样式表中的规则排序靠后(因为@import相当于放在文档最头部)
4)最后排序最高位的规则胜出


三、链接伪类的LVHA

在对a标签设置伪类时,应当按照LVHA或者VLHA的顺序进行编写,即:

a:link { /* ... */ }
a:visited { /* ... */ }
a:hover { /* ... */ }
a:active { /* ... */ }

这也是由于优先级计算的原因。如果我们以以下顺序编写的话:

a:hover { /* ... */ }
a:active { /* ... */ }
a:link { /* ... */ }
a:visited { /* ... */ }

那么任何时候,hoveractive的样式都不会生效。这是因为:
在鼠标移到链接上的时候,激活了伪类:hover,但是由于链接要么是已访问过的,要么是未访问的,而由于:link:visited都写在下面,在CSS计算优先级后,排序后就会是:link:visited胜出,所以hover中的相关样式就不会生效了


四、总结

综合以上分析,可以给出CSS优先级的结论:
!important > 内联规则 > ID选择器 > 类选择器、属性选择器、伪类选择器 > 元素选择器、伪元素选择器 > 通配符选择器