MinimalistYing.io

浅谈 CSS(Cascading Style Sheets) 之层叠

对页面上的每一个元素来说,通常会有很多样式应用于其上,但是一个元素不可能背景色既是红色又是绿色。

所以当样式的定义发生冲突时浏览器会通过如下规则来判断最终采用哪条规则来渲染元素。

  1. 重要性 Importance
  2. 特殊性 Specificity
  3. 先后顺序 Order

这个过程就称为样式的层叠 (Cascade)。

重要性

重要规则(包含关键字 !important)优先于普通规则,例如页面包含如下样式:

p { color: red !important }

那么无论你在何处以什么样的选择器去定义另外的 color 只要不使用 !important 段落的字体颜色最终都是红色

如果是俩条重要规则发生冲突呢 ?
首先根据来源判断:读者定义的重要规则 > 开发人员定义的重要规则

如果把普通规则也加入排序的话:
读者定义的重要规则 > 开发人员定义的重要规则 > 开发人员定义的普通规则 > 读者定义的普通规则 > 浏览器默认规则

如果俩条重要规则的来源相同呢 ?
那么先考虑特殊性(下文会讲):特殊性高 > 特殊性低

如果特殊性也一致呢 ?
考虑规则在样式表中的先后顺序 : 后定义 > 先定义

Ps: 通常来说不建议使用 !important 除非你需要覆盖一些不受你控制的内联样式

特殊性

特殊性是针对选择器而言的,首先我们定义特殊性 0 1 0 0 > 0 0 2 0 > 0 0 0 3 > 0 0 0 0

内联样式没有选择器 特殊性永远为 1 0 0 0,所以内联样式比所有定义在外部样式表中的样式特殊性都要高。

规则中每出现一个 ID 选择期特殊性增加 0 1 0 0

每出现一个类选择器/伪类选择器/属性选择器特殊性增加 0 0 1 0

每出现一个元素选择器/伪元素选择器增加 0 0 0 1

连接符/通配符特殊性为 0 0 0 0

继承而来的规则没有特殊性。

Ps: 需要特别注意的一点是特殊性为 0 0 0 0 和没有特殊性是不一样的
简单来讲就是通配符设置的样式会覆盖掉元素继承而来的样式,这点很容易导致问题,所以通常不建议使用通配符来设置页面样式

下面举几个例子来更好的理解特殊性,有如下 HTML

<div id="box" class="parent">
  <p id="content" class="son"></p>
</div>

又有如下几组样式

/* 0 1 0 0 */
#content {
  background: red;
}
/* 0 0 1 1 */
p.son {
  background: green;
}

由于 0 1 0 0 的特殊性比 0 0 1 1 高,所以背景色为红色

/* 0 2 0 0 */
#box > #content {
  background: green;
}
/* 0 1 2 1 */
div.parent > #content[class^=s] {
  background: red;
}

由于 0 2 0 0 的特殊性比 0 1 2 1 要高,所以背景色为绿色

/* 0 0 1 0 */
.parent {
  background: green;
}
/* 0 0 1 1 */
.parent:hover {
  background: red;
}

由于 0 0 1 1 的特殊性比 0 0 1 0 要高,所以在鼠标 hover 时背景色会变为红色

先后顺序

如果一条规则的重要性/来源/特殊性都一致,则在样式表中越靠后出现的声明优先级越高

总结

对于作用于同一元素的任意俩条规则,想要判断哪条规则最终会生效的话
首先比较来源 > 来源相同再比较重要性 > 重要性相同再比较特殊性 > 都相同最后比较先后顺序
这样最终总能确认哪一条规则会胜出