特殊性(specificity)

当不同选择器选择了相同的元素的时候,不同的声明会综合在一起,而相同属性的声明则需要判断到底应用哪个,这个判断的量我们称之为“特殊性”

特殊性的表述分为四个部分,可以表示为:0, 0, 0, 0

  • 对于ID选择器(#id),贡献0, 1, 0, 0
  • 对于类选择器(.class)、 属性选择器([class], [class=”class1”])和伪类选择器(:hover, :link, …),贡献0, 0, 1, 0
  • 对于元素选择器(h1)和伪元素选择器(:first-word, …),贡献0, 0, 0, 1
  • 结合符(+, >)和通配选择器(*),没有贡献

例如:

#tag.post-tag > h1 + p {color:red;}

其特殊性为:0, 1, 1, 2

在比较不同选择器的特殊性时,要按位比较,如0, 0, 0, 2 > 0, 0, 0, 1, 0, 0, 1, 0 > 0, 0, 0, 1。 而在整体比较的过程中顺序是从左到右的,只要从左到右有一位产生了大小的分别,即拥有了大小的分别,例如: 0, 1, 0, 7 > 0, 0, 1, 13。

声明和特殊性

一旦确定一个选择器的特殊性,这个值将授予所有相关声明。

例如:

h1 {color: red;background: black;}

用户代理将其“解组”为单独的规则并计算特殊性

h1 {color: red;} /* 0, 0, 0, 1 */
h1 {background: black;} /* 0, 0, 0, 1 */

如果多个规则应用到同一个元素上并且有些声明相互冲突,那么这些规则之间将比较特殊性,绝对最后应用的样式。

内联样式特殊性

你可能会思考,为什么特殊性由四位构成,第一位的作用是什么?看下面的代码:

h1 {color:red;}
<h1 style="color: green;">The Meadow Party</h1> 

最后h1元素的颜色是绿色而不是红色,其原因在于绿色是内联声明的,其特殊性为1, 0, 0, 0

重要性

有时某个声明可能非常重要,超过了所有其他声明。CSS2.1称之为“重要声明”,允许在分号前插入!important来标识,例如:

h1 {color: red !important;}

必须正确放置!important的位置,即放在声明的末尾分号前,否则将不生效。

标志为!important并没有影响特殊性,不过要与非重要声明分开考虑。如果一个重要声明和一个非重要声明冲突,那么胜出的总是非重要声明。

继承

特殊性对于理解如何向文档应用声明很重要,同样的还有一个很重要的概念,即继承。基于继承机制,样式不仅应用到指定的元素,还会应用到它的后代元素。例如:

<h1 style="color:red">This is <em>Sparta</em></h1>

包括所有h1的子元素颜色也将被渲染成红色。

继承属性是CSS最基本的内容之一,一般不会特别考虑,但是还是要记住的是:

  • 大部分框模型属性(如border)不会继承
  • 继承没有特殊性,且低于0,0,0,0, 如 * {color: red;}

层叠

还有一种情况要考虑的是,当特殊性相同的两个规则同时应用到同一个元素会如何?处理规则是有规定的。

“层叠样式表”这个名字可能会提供一点提示。CSS所基于的方法就是让样式层叠在一起,这时通过结合继承和特殊性做到的。CSS2.1的层叠规则相当简单:

  1. 找出所有规则,这些规则都包含与一个给定元素匹配的选择器
  2. 按显示权重应用到钙元素的所有声明排序
  3. 按特殊性对应用到给定元素的所有声明排序
  4. 按出现顺序对应用到给定元素的所有声明排序。一般认为出现的越晚,权重越高

按权重和来源排序

从权重方面讲,有!imporant标志的胜于无!imporant标志的

而如果重要级相同的话,就要从来源考虑。从来源方面讲,一般考虑五级,而开发人员通常考虑四级

  1. 浏览用户的重要声明(Reader important declarations)。例如系统设置之类的
  2. 开发人员的重要声明(Author important declarations)
  3. 开发人员的正常声明(Author normal declarations)
  4. 浏览用户的正常声明(Reader normal declarations)
  5. 浏览器的自带声明(User agent declarations)

按特殊性排序

如同特殊性部分介绍的那样,如果权重相同,那么就按照特殊性进行排序

按顺序排序

在权重和特殊性都相同时,那么就要按照声明的顺序来比较了,一般来说声明越晚,其权重越大

正是由于这种按顺序排序,所以才有了通常推荐的链接样式顺序。一般建议按照link-visited-hover-active(LVHA,LoVe-HA)的顺序声明。

假设反过来,那么任何连接都不会显示:hover或:active样式,因为:link和:visited规则出现后,所有链接要么是已访问的,要么是未访问的,所以:link和:visited样式总是会覆盖:hover规则。

非CSS表现提示

文档可能包含非CSS表现提示,例如font元素。这种被处理为特殊性为零。

其实现在已经基本淘汰了这种元素,就不深研究了。

小结

“层叠样式表”的“层叠”表示了各个样式在计算时的这种特性——冲突的声明要通过这种层叠过程排序,并由此确定最终文档的表示。这个过程的核心是选择器及其相关声明的特殊性,以及继承机制