重学CSS之层叠

114 阅读5分钟

CSS,即层叠样式表(英文全称:Cascading Style Sheets),本系列第一篇就来讲CSS中的第一个C,即层叠(Cascading)。

浏览器遵循三个步骤,即来源、优先级、源码顺序,来解析网页上每个元素的每个属性。


1、来源

你添加到网页里的样式表并不是浏览器唯一使用的样式表,还有其他类型或来源的样式表。你的样式表属于作者样式表,除此之外还有用户代理样式表,即浏览器默认样式。用户代理样式表优先级低,你的样式会覆盖它们。

1.1 用户代理样式

浏览器应用了用户代理样式后才会应用你的样式表,即作者样式表。你指定的声明会覆盖用户代理样式表里的样式。如果你在HTML里面链接了多个样式表,那么它们的来源都相同,即作者。

1.2 !important 声明

样式来源规则有一个例外:标记为重要(important)的声明。如下所示,在声明的后面、分号的前面加上!important,该声明就会被标记为重要的声明。

color: red !important;

标记了!important的声明会被当作更高优先级的来源,因此总体的优先级按照由高到低排列如下所示:

  1. 作者的 !important
  2. 作者
  3. 用户代理

2、优先级

如果无法用来源解决冲突声明,浏览器会尝试检查它们的优先级。浏览器将优先级分为两部分:HTML的行内样式和选择器的样式。

2.1 行内样式

如果用HTML的style属性写样式,这个声明只会作用于当前元素。实际上行内元素属于“带作用域的”声明,它会覆盖任何来自样式表或者标签的样式。行内样式没有选择器,因为它们直接作用于所在的元素。

2.2 选择器优先级

优先级的第二部分由选择器决定。比如,有两个类名的选择器比只有一个类名的选择器优先级更高。

优先级的准确规则如下:

  1. 如果选择器的ID数量更多,则它会胜出(即它更明确)。
  2. 如果ID数量一致,那么拥有最多类的选择器胜出。
  3. 如果以上两次比较都一致,那么拥有最多标签名的选择器胜出。

伪类选择器(如:hover)和属性选择器(如[type="input"])与一个类选择器的优先级相同。通用选择器(*)和组合器(>、+、~)对优先级没有影响。

2.3 优先级标记

一个常用的表示优先级的方式是用数值形式来标记,通常用逗号隔开每个数。比如,“1,2,2”表示选择器由1个ID、2个类、2个标签组成。优先级最高的ID列为第一位,紧接着是类,最后是标签。


3、源码顺序

层叠的第三步,也是最后一步,是源码顺序。如果两个声明的来源和优先级相同,其中一个声明在样式表中出现较晚,或者位于页面较晚引入的样式表中,则该声明胜出。

也就是说,可以通过控制源码顺序,来给特殊链接添加样式。如果两个冲突选择器的优先级相同,则出现得较晚的那个胜出。

3.1 链接样式和源码顺序

你刚开始学习CSS时,或许就知道给链接加样式要按照一定的顺序书写选择器。这是因为源码顺序影响了层叠。下列代码展示了如何以“正确”的顺序书写链接样式。

a:link {
    color: blue;
    text-decoration: none;
}

a:visited {
    color: purple;
}

a:hover {
    text-decoration: underline;
}

a:active {
    color: red;
}

书写顺序之所以很重要,是因为层叠。优先级相同时,后出现的样式会覆盖先出现的样式。

这个顺序的记忆口诀是“LoVe/HAte”(“爱/恨”),即link(链接)、visited(访问)、hover(悬停)、active(激活)。

3.2 层叠值

浏览器遵循三个步骤,即来源、优先级、源码顺序,来解析网页上每个元素的每个属性。如果一个声明在层叠中“胜出”,它就被称作一个层叠值。元素的每个属性最多只有一个层叠值。网页上一个特定的段落(

)可以有一个上外边距和一个下外边距,但是不能有两个不同的上外边距或两个不同的下外边距。如果CSS为同一个属性指定了不同的值,层叠最终会选择一个值来渲染元素,这就是层叠值。如果一个元素上始终没有指定一个属性,这个属性就没有层叠值。还是拿段落举例,可能就没有指定的边框或者内边距。


4、两条经验法则

**(1) 在选择器中不要使用ID。**就算只用一个ID,也会大幅提升优先级。当需要覆盖这个选择器时,通常找不到另一个有意义的ID,于是就会复制原来的选择器,然后加上另一个类,让它区别于想要覆盖的选择器。

**(2) 不要使用!important。**它比ID更难覆盖,一旦用了它,想要覆盖原先的声明,就需要再加上一个!important,而且依然要处理优先级的问题。

这两条规则是很好的建议,但不必固守它们,因为也有例外。不要为了赢得优先级竞赛而习惯性地使用这两个方法。