CSS 特指度和层叠

1、特指度

我们可以使用多种不同的方法选择元素。实际上,同一个元素可能会被两个多或多规则选择,而且每个规则的选择符不尽相同。最终相同的规则只有一个胜出,最终应用到元素上。那么我们如何知道哪个规则胜出呢?

答案隐藏在每个选择符的特指度中。用户代理会计算每个规则中选择符的特指度,然后将其依附到规则中的每个声明上。如果两个或多个属性声明有冲突(相同),特指度最高的声明胜出。

特指度值由选择符本身的组成部分决定,由四个部分构成,例如:0,0,0,0。特择符特指度通过下述规则确定:

  • 选择符中的每个ID属性值加 0,1,0,0
  • 选择符中的每个类属性值、属性选择或伪类加 0,0,1,0
  • 选择符中的每个元素为伪元素加 0,0,0,1
  • 连结符和通用选择符不增加特指度

例如,下面组出几个规则中选择符的特指度:

h1 { color: red; }                           /* 0,0,0,1 元素 */
p em { color: purple; }                      /* 0,0,0,2 元素 + 元素 */
.grape { color: purple; }                    /* 0,0,1,0 类 */
*.bright { color: yellow; }                  /* 0,0,1,0 类 + 通用 */
p.bright em.dark { color: maroon; }          /* 0,0,2,2 元素.类 + 元素.类 */
#id216 { color: blue; }                      /* 0,1,0,0 ID选择 */
div#sidebar *[href] { color: silver; }       /* 0,1,1,1 元素 + ID + 属性选择 */

2、行内样式的特指度

目前见到的特指度都以零开头,因此可能在想,那第1位为什么要存在呢?存在必定有用。第1位是为行内样式声明保留的,行内样式声明的特指度比其他声明都要高。对下面的规则和标记片段来说:

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

即便那个规则会应用到 h1 元素上,但是 h1 元素中的文本仍然显示为绿色。这是因为行内声明的特指度为 1,0,0,0

3、重要性

有时某个声明可能非常重要,超过其他所有声明。这时就会在声明末尾的分号之前插入 !important,例如:

p.dark { color: #333 !important; background: white; }

如果 !important 放的位置不正确,整个声明都效失效,而且整个样式都不会应用到元素上。

带有 !important 的声明对特指度没有影响,但是会与不重要的声明分开处理。其实,所有带 !important 的声明会放在一起,而特指度冲突就在这个范围内解决。因此,重要声明和非重要声明冲突时,重要声明始终胜出。

4、层叠

如果两个特指度相等的规则应用到同一个元素上会发生什么?浏览器如何解决这样的冲突呢?

h1 { color: red; }
h1 { color: bule; }

哪一个规则胜出?两个规则的特指度都是 0,0,0,1,因此它们的权重相同。

CSS采用层叠机制把样式组合在一起,即结全继承和特指度的一些规则。CSS的层叠规则如下:

  1. 找到匹配特定元素的所有规则。
  2. 按显示权重排序应用到特定元素上的所有声明。
  3. 按来源排序应用到特定元素上的所有声明。
  4. 按特指度排序应用到特定元素上的所有声明。
  5. 按声明的前后位置排序应用到特定元素上的所有声明。

4.1、按权重和来源

在声明的权重上,基本要考虑五个方面。下面按权重从高到低列出:

  1. 读者提供的样式中以 !important 标记的声明
  2. 创作人员编写的样式中以 !important 标记的声明
  3. 创作人员编写的常规声明
  4. 读者提供的常规声明
  5. 用户代理的默认声明

创作人员通常只需要考虑前四点,因为创作人员编写的任何样式都会覆盖用户代理的默认样式。

4.2、按前后位置

如果两个规则的显式权重、来源和特指度都相同,那么在样式表中的位置靠后的规则胜出。