CSS,即层叠样式表(英文全称:Cascading Style Sheets),本系列第一篇就来讲CSS中的第一个C,即层叠(Cascading)。
浏览器遵循三个步骤,即来源、优先级、源码顺序,来解析网页上每个元素的每个属性。
1、来源
你添加到网页里的样式表并不是浏览器唯一使用的样式表,还有其他类型或来源的样式表。你的样式表属于作者样式表,除此之外还有用户代理样式表,即浏览器默认样式。用户代理样式表优先级低,你的样式会覆盖它们。
1.1 用户代理样式
浏览器应用了用户代理样式后才会应用你的样式表,即作者样式表。你指定的声明会覆盖用户代理样式表里的样式。如果你在HTML里面链接了多个样式表,那么它们的来源都相同,即作者。
1.2 !important 声明
样式来源规则有一个例外:标记为重要(important)的声明。如下所示,在声明的后面、分号的前面加上!important,该声明就会被标记为重要的声明。
color: red !important;
标记了!important的声明会被当作更高优先级的来源,因此总体的优先级按照由高到低排列如下所示:
- 作者的 !important
- 作者
- 用户代理
2、优先级
如果无法用来源解决冲突声明,浏览器会尝试检查它们的优先级。浏览器将优先级分为两部分:HTML的行内样式和选择器的样式。
2.1 行内样式
如果用HTML的style属性写样式,这个声明只会作用于当前元素。实际上行内元素属于“带作用域的”声明,它会覆盖任何来自样式表或者标签的样式。行内样式没有选择器,因为它们直接作用于所在的元素。
2.2 选择器优先级
优先级的第二部分由选择器决定。比如,有两个类名的选择器比只有一个类名的选择器优先级更高。
优先级的准确规则如下:
- 如果选择器的ID数量更多,则它会胜出(即它更明确)。
- 如果ID数量一致,那么拥有最多类的选择器胜出。
- 如果以上两次比较都一致,那么拥有最多标签名的选择器胜出。
伪类选择器(如: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,而且依然要处理优先级的问题。
这两条规则是很好的建议,但不必固守它们,因为也有例外。不要为了赢得优先级竞赛而习惯性地使用这两个方法。