JobbyM's Blog

一日一练-CSS 选择器的特殊性

子曰:更好的确认CSS 的最终规则
参考《CSS 权威指南》第3 章 结构和层叠 特殊性

在实际工作中,总会遇到一个元素可以使用两个或多个规则来选择,每一个规则都有自己的选择器。
假设下面每一对规则都匹配同样的元素,由于所匹配的元素只能是某一种颜色(二选一),如何确认那一个规则更强呢?

1
2
h1 { color: red; }
body h1 { color: green; }
1
2
h2.grape { color: purple; }
h2 { color: silver; }
1
2
html > body table tr[id="totals"] td ul > li { color: maroon; }
li#answer { color: green; }

解决的方法就是每个选择器的特殊性(specificity)。对于每个规则,用户代理会计算选择器的特殊性,并将这个特殊性附加到规则中的各个声明中。如果一个元素有两个或多个冲突的声明,那么有最高特殊性的声明就会胜出。

选择器的特殊性由选择器本身的组件确定的。特殊性值表述为4 个部分,如:0,0,0,0
一个选择器的具体特殊性如下确定:

  • 对于选择器中给定的各个ID 属性值,加0,1,0,0
  • 对于选择器中给定的各个类属性值、属性选择器或伪类,加0,0,1,0
  • 对于选择器中给定的各个元素和伪元素,加0,0,0,1。伪元素是否具有特殊性?在这方面CSS2 有些自相矛盾,不过CSS2.1 很清楚地指出,伪元素有特殊性,而且特殊性为0,0,0,1.
  • 结合符和通配选择器对特殊性没有任何贡献。

根据这个规则,计算文章开头的几组规则的特殊性

1
2
h1 { color: red; }        /* specificity = 0,0,0,1 */
body h1 { color: green; } /* specificity = 0,0,0,2 (winner)*/
1
2
h2.grape { color: purple; } /* specificity = 0,0,1,1 (winner)*/
h2 { color: silver; } /* specificity = 0,0,0,1 */
1
2
html > body table tr[id="totals"] td ul > li { color: maroon; } /* specificity = 0,0,1,7 */
li#answer { color: green; } /* specificity = 0,1,0,1 (winner)*/

上面已经指出每组规则中的胜出规则
注意

  1. 因为值是从左向右排序的。特殊性值1,0,0,0 大于以0 开头的所有特殊性值,而不论后面的数是什么。所以特殊性值0,0,1,7 小于0,1,0,1
  2. 每个内联声明的特殊性都是1,0,0,0。也就是说内联声明的特殊性最高。
  3. 重要声明,即在声明的结束分号之前插入!important 比上述的声明的特殊性都高。