CSS主要有三个基本特性:继承、权重和层叠。
CSS样式解析过程
我们知道,浏览器会将HTML文档解析为一颗DOM树,以便确定父子、祖先、兄弟等关系,并根据元素的关系匹配相应的样式。
同样,浏览器也会对CSS文件进行解析,我们书写的CSS代码看起来是这样的:
1
2
3
4
5
6
7
8
h1 {
color: red;
font-size: 20px;
}
body h1 {
color: pink;
}
而实际上浏览器会将css代码按选择器和样式分别解,得到下列声明:
1
2
3
h1 {color: red};
h1 {font-size: 20px};
body h1 {color: pink};
很显然,选择器h1
和body h1
之间出现了样式冲突,最终h1
的字体颜色应该是红色还是粉色呢?
层叠和权重正是在这样的背景下产生的,他们规定了样式出现冲突时,应该使用哪一种样式。
继承
CSS中,子元素会从父元素上继承某些样式。例如:
1
2
3
4
body {
color: red;
font-size: 16px;
}
1
2
3
<body>
<p>这是一段文字</p>
</body>
尽管我们并没有给p
指定p {color: red};
这样的样式,但p
中的文字仍然为红色,这是因为他从父元素中继承了颜色样式。
继承是CSS一个明显的特性,通常情况下无需单独考虑,但也有几点需要注意:
- 很多属性是不继承的,是为了避免出现意外情况。例如
border
属性,如果允许继承,则边框内的文字会变得异常杂乱。 - 此外,基于同样原因,盒模型的多数属性都不允许继承,如内边距、外边距等。
权重
权重也叫特指度,主要用于解决不同选择器指定同一样式时的冲突问题,根据选择器权重确定优先性,权重高的优先级高。
CSS中的权重是一个四个维度的向量,例如$(0, 0, 0, 1)$。权重高低按照从左到右的顺序依次比较,靠左的分量值越大,权重越大;若出现某一分量相等,则比较下一分量,例如:$(1, 0, 0, 0)$将始终大于$(0, 99, 99, 99)$,因为他最左侧的分量胜出。
基本选择器的权重
- 行内样式 $(1, 0, 0, 0)$
- ID选择器 $(0, 1, 0, 0)$
- 类选择器、伪类选择器、属性选择器 $(0, 0, 1, 0)$
- 元素选择器、伪元素选择器 $(0, 0, 0, 1)$
- 通配选择器 $(0, 0, 0, 0)$
复合选择器的权重
通常情况下,复合选择器的符号(如,
, +
, ~
)无权重,因此计算一条规则时只需要将该规则所包含的基本选择器权重累加即可。例如
1
2
3
h1, h2.section {
color: silver
}
在用户代理眼中是这样的:
1
2
h1 {color: silver} /* (0, 0, 0, 1) */
h2.section {color: silver} /* (0, 0, 1, 1) */
任何情况下,用户代理都会确定哪些规则和元素相配,然后找出相关的声明,计算各自的权重,权重高的获胜,再把胜出规则的样式加在对应元素上。
重要性
根据基本选择器的权重可知,最高权重应该是行内样式,但有些时候某条声明可能很重要,超过了其他所有声明,CSS称为重要性声明,即在对应样式的分号之前加上!important
。例如:
1
2
3
.danger {
color: red !important;
}
带有!important
不会影响该条规则的权重,但他会与不重要的声明分开处理,也就是说,用户代理会先考虑重要声明,然后才会根据权重去处理那些“不重要”的声明,即重要规则永远胜出。
要特别注意的是,继承的样式不具有权重,继承的元素权重甚至低于通配选择器的“0权重”。 例如:
1
2
3
4
5
6
7
* {
color: pink;
}
p {
color: red;
}
1
2
3
<body>
<p>这是一段<em>文字</em></p>
</body>
首先,元素选择器权重大于通配选择器,因此p
内文字应该是红色;
其次,em
从p
中继承了红色,继承的样式具有最低的权重,通配选择器胜出,因此最终的“文字”这一文本的颜色为粉色。
层叠
如果说权重主要用于解决不同选择器之间的样式冲突问题,那么层叠则是为了解决同一选择器间的样式问题。例如:
1
2
3
4
5
6
7
h1 {
color: red;
}
h1 {
color: blue;
}
最终h1
的颜色是蓝色还是红色呢? 答案是蓝色,这是由于CSS的层叠性导致的。
CSS层叠性保证按照就近原则排序,即后声明的样式会覆盖掉先声明的样式。
这也就是为什么我们要求超链接伪类的书写顺序尽量为link-visited-focus-hover-active:
- 首先,上述所有伪类选择器的权重都是$(0, 0, 1, 0)$,因此应当考虑层叠性。
- 如果
:link
和:visited
在最后,那么一个链接或者被访问,或者未被访问,根据层叠性,他们将覆盖掉其他所有样式。
CSS样式优先级规则
根据继承、权重、层叠三大特性,我们可以看出CSS层叠样式表处理样式优先级时的规则:
- 找到匹配特定元素的所有规则。
- 按照显式权重排序,
!important
样式具有最高的优先级。 - 按照来源排序。
读者!important
>创作者!important
>创作者
>读者
>用户代理
- 按照特指度权重排序,特指度高的样式具有更高的优先级。
- 按照声明的前后顺序排序,靠后声明的样式具有更高的优先级。