Skip to content
On this page

CSS 规则的特性

特指度

我们可以使用各种各样的选择符来选择元素,在多个选择符选择到同一个元素时,如果它们之间的声明有冲突,那么应用到这个元素的声明会是哪个呢?

例如,对下述三对规则来说,假设每一对规则选择的元素相同:

css
h1 {
  color: red;
}
body h1 {
  color: green;
}

h2.grape {
  color: purple;
}
h2 {
  color: silver;
}

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

用户代理 (浏览器) 会计算每个规则中选择符的特指度,然后将其依附到规则中的每个声明上。如果两个或多个声明有冲突,一般特指度最高的声明优先。

确定特指度

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

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

例如,对下述几个规则中选择符确定特指度:

css
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 **/
div#sidebar *[href] {
  color: silver;
} /** 特指度 = 0,1,1,1 **/

通用选择符的特指度

通用选择符不增加特指度。也就是说,它的特指度为 0,0,0,0

例如,对下述两个规则来说,div 元素中的 p 元素将显示为 black,其他元素则显示为 gray:

css
div p {
  color: black;
} /* 0,0,0,2 */
* {
  color: gray;
} /* 0,0,0,0 */

id 和属性选择符的特指度

id 选择符和选择 id 属性的属性选择符之间在特指度上是有区别的。

例如,对下述两个规则来说,id 为 meadow 的元素将显示为 green:

css
#meadow {
  color: green;
} /* 0,1,0,0 */
*[id="meadow"] {
  color: red;
} /* 0,0,1,0 */

行内样式的特指度

目前见到的特指度都以零开头,因此你可能在想,那第一位为什么要存在呢?存在必定有用。那一位是为行内样式声明保留的,行内样式声明的特指度比其他声明都高。

例如,对下述规则和标记片段来说,h1 元素将显示为 green:

css
h1 {color: red;}																/* 0,0,0,1 */
<h1 style="color: green;">The Meadow Party</h1> /* 1,0,0,0 */

重要性

有时某个声明可能非常重要,超过其他所有声明。CSS 称之为重要声明 (important declaration)。这种声明要在声明末尾的分号之前插入 !important

例如,对下述规则和标记片段来说,p 元素将显示为 #333 颜色:

css
p.dark {color: #333 !important; background: white;}
<p class="dark" style="color: green;">The dark</p>

继承

继承指某些声明不仅会应用到所指的元素上,还会应用到元素的后代上。

例如,对下述规则和标记片段来说,因为 color 声明是可以继承的,所以 h1 元素设定的 color 不仅会应用到自身,还会应用到它的后代元素中:

css
h1 {color: gray;}
<h1>Meerkat <em>Central</em></h1>

注意,继承的值没有特指度,连零都没有;而通用选择符有特指度 0,0,0,0。因此,通用选择符的声明会优先于继承的声明。

例如,对下述规则和标记片段来说,em 元素渲染为 gray,而不是继承的 black:

css
* {color: gray;}
h1#page-title {color: black;}

<h1 id="page-title">Meerkat <em>Central</em></h1>
<p>Welcome to the best place on the web for meerkat information!</p>

层叠

如果两个特指度相等的规则应用到同一个元素上会发生什么?

例如,对下述规则来说:

css
h1 {
  color: red;
}
h1 {
  color: blue;
}

哪一个规则优先?两个规则的特指度都是 0,0,0,1,因此它们的权重相同,都应该应用到元素上。但事实并非如此,因为元素的内容不可能即是红色的,又是蓝色的。那到底是什么颜色呢?

CSS (Cascading Style Sheets,层叠样式表),CSS 采用层叠机制把样式组合在一起,即结合继承和特指度的一些规则。具体规则如下:

  1. 找到匹配特定元素的所有规则。
  2. 按显示权重排序应用到特定元素上的所有声明。以 !important 标记的规则比没有这一标记的权重高。
  3. 按来源排序应用到特定元素上的所有声明。声明有三个来源:创作人员、读者和用户代理。正常情况下,创作人员编写的样式击败读者提供的样式;读者样式中以 !important 标记的声明比其他样式权重高,包括创作人员编写的样式中以 !important 标记的声明;创作人员和读者样式覆盖用户代理的默认样式。
  4. 按特指度排序应用到特定元素上的所有声明。特指度高的声明具有较高的权重。
  5. 按声明的前后位置排序应用到特定元素上的所有声明。样式表或文档中靠后的声明权重较高。@import 导入的样式表中的声明放在当前样式表中所有声明的前面。

按权重

如果两个规则应用到同一个元素上,而其中一个以 !important 标记,那么有此标记的规则优先。

例如,对下述规则和标记片段来说,p 元素渲染为 gray:

css
p {color: gray !important;}
<p style="color: black;">Well, <em>hello</em> there!</p>

按来源排序

如果显式权重相同,就要考虑规则的来源。正常情况下,如果匹配元素的两个样式权重相同,而一个在创作人员编写的样式表中,另一个在读者提供的样式表中,那么元素将使用创作人员编写的样式表中的样式。

例如,对于下述规则来说,两个样式分别来自指定的位置:

css
p em {
  color: black;
} /* 创作人员编写的样式表 */
p em {
  color: yellow;
} /* 读者提供的样式表 */

然而,如果两个规则都用 !important 标记,那情况就变了 (将显示为 yellow):

css
p em {
  color: black !important;
} /* 创作人员编写的样式表 */
p em {
  color: yellow !important;
} /* 读者提供的样式表 */

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

  • 读者提供的样式中以 !important 标记的声明。
  • 创作人员编写的样式中以 !important 标记的声明。
  • 创作人员编写的常规声明。
  • 读者提供的常规声明。
  • 用户代理的默认声明。

按特指度排序

如果应用到同一个元素上的声明有冲突,而且各声明的显式权重和来源相同,那么应该按特指度排序,特指度最高的声明优先。

例如,对下述规则和标记片段来说,p 元素将显示为 silver:

css
p#bright {color: silver;}
p {color: black;}

<p id="bright">Well, hello there!</p>

按前后位置排序

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

例如,对下述规则来说,h1 元素将显示为 blue:

css
h1 {
  color: red;
}
h1 {
  color: blue;
}