优先级和继承
本文介绍 CSS 的一些最基本的概念: 层叠、优先级和继承。
冲突规则
CSS 代表层叠样式表,我们需要理解第一个词 cascading。
Cascade, 和它密切相关的概念是 Specificity,决定在发生冲突的时候应该使用哪条规则。
这里也有继承的概念,也就是在默认情况下,一些 CSS 属性继承当前元素的父元素上设置的值,有些则不继承。这也可能导致一些和期望不同的结果。
层叠
Style sheets cascade(样式表层叠) 决定了 CSS 规则的顺序很重要。
当应用两条同级别的规则到一个元素的时候,写在后面的就是实际使用的规则。
案例: 我们有两个关于 h1
的规则。这些规则有相同的优先级,顺序在最后的生效,所以 h1
最后显示为蓝色。
<h1>Shimon Zhan is handsome!</h1>
h1 {
color: red;
}
h1 {
color: blue;
}
优先级
浏览器是根据优先级来决定当多个规则有不同选择器对应相同的元素的时候需要使用哪个规则。它基本上是一个衡量选择器具体选择哪些区域的尺度:
- 一个元素选择器不是很具体 (它会选择页面上该类型的所有元素),所以它的优先级就会低一些。
- 一个类选择器稍微具体点 (它会选择该页面中有特定 class 属性值的元素),所以它的优先级就要高一点。
上面的 h1
会显示红色 (类选择器有更高的优先级,即使元素选择器顺序在它后面)。
<h1 class="main-heading">Shimon Zhan is handsome!</h1>
.main-heading {
color: red;
}
h1 {
color: blue;
}
继承
一些设置在父元素上的 CSS 属性是可以被子元素继承的,有些则不能。
案例: 如果您设置一个元素的 color
和 font-family
,默认情况下每个在里面的元素也都会有相同的属性。
/* 整个文档的文字默认情况下都是蓝的,除非针对性的设置为其他颜色 */
body {
color: blue;
}
注意
一些属性是不能继承的。比如您在一个元素上设置 width: 50%
,所有的后代不会是父元素的宽度的 50%。如果这个也可以继承的话,CSS 就会很难使用了!
理解继承
我们从继承开始。下面的例子中我们有一个 ul
,里面有两个无序列表。我们已经给 <ul>
设置了 border
, padding
和 color
.
color
应用在直接子元素,也影响其他后代,如子元素 <li>
,和第一个嵌套列表中的子项。然后添加了一个 special
类到第二个嵌套列表。该类声明了不同的颜色。然后通过它的子元素继承。
<ul class="main">
<li>Item One</li>
<li>
Item Two
<ul>
<li>2.1</li>
<li>2.2</li>
</ul>
</li>
<li>
Item Three
<ul class="special">
<li>
3.1
<ul>
<li>3.1.1</li>
<li>3.1.2</li>
</ul>
</li>
<li>3.2</li>
</ul>
</li>
</ul>
.main {
color: rebeccapurple;
border: 2px solid #ccc;
padding: 1em;
}
.special {
color: black;
font-weight: bold;
}
像 width
(上面提到的), margin
, padding
, 和 border
不会被继承。如果 border
可以被继承,每个列表和列表项都会获得一个边框 — 可能就不是我们想要的结果!
哪些属性属于默认继承很大程度上是由常识决定的。
控制继承
CSS 为控制继承提供了四个特殊的通用属性值。每个 CSS 属性都接收这些值。
inherit
: 使子元素属性和父元素相同。实际上就是 "开启继承".initial
: 与浏览器默认样式相同。如果浏览器默认样式中未设置且该属性是自然继承的,那么会设置为inherit
。unset
: 将属性重置为自然值,也就是如果属性是自然继承那么就是inherit
,否则和initial
一样
相关信息
还有一个属性 revert
,但只有很少的浏览器支持。
重设所有属性值
CSS 的缩写属性 all
可以用于同时将这些继承值中的一个应用于(几乎)所有属性。它的值可以是其中任意一个(inherit
, initial
, unset
, revert
)。这是一种撤销对样式所做更改的简便方法,以便回到默认状态。
<blockquote>
<p>This blockquote is styled</p>
</blockquote>
<blockquote class="fix-this">
<p>This blockquote is not styled</p>
</blockquote>
blockquote {
background-color: red;
border: 2px solid green;
}
.fix-this {
all: unset;
}
理解层叠
有三个因素需要考虑,根据重要性排序如下:
- 重要程度
- 优先级
- 资源顺序
我们从下往上,看看浏览器是如何决定该应用哪个 CSS 规则的。
资源顺序
我们已经看到了顺序对于层叠的重要性。如果您有超过一条规则,而且都是相同的权重,那么最后面的规则会应用。可以理解为后面的规则覆盖前面的规则,直到最后一个开始设置样式。
优先级计算
在您了解了顺序的重要性后,会发现在一些情况下,有些规则在最后出现,但是却应用了前面的规则。
只要前面的有更高的优先级,浏览器就把它选择为元素的样式。就像前面看到的,类选择器的权重大于元素选择器,因此类上定义的属性将覆盖应用于元素上的属性。
注意
虽然我们考虑的是选择器,但是只有相同的属性会被覆盖,不会覆盖所有规则,也就是说优先级低的选择器的其他不冲突声明仍会生效。
技巧
一种常见的做法是给基本元素定义通用样式,然后给不同的元素创建对应的类。
比如我的博客对很多标签的样式进行了调整(比如减小了 <h1>
的字体大小以及标题的字体粗细),并通过类来对特定区域的标签进行进一步的样式调整。
本质上,不同类型的选择器有不同的分数值,把这些分数相加就得到特定选择器的权重,然后就可以进行匹配。
一个选择器的优先级可以说是由四个部分相加 (分量),可以认为是个十百千 — 四位数的四个位数:
- 千位: 如果声明在 style 的属性(内联样式)则该位得一分。这样的声明没有选择器,所以它得分总是 1000。
- 百位: 选择器中包含 ID 选择器则该位得一分。
- 十位: 选择器中包含类选择器、属性选择器或者伪类则该位得一分。
- 个位: 选择器中包含元素、伪元素选择器则该位得一分。
注意
通用选择器 (*
),组合符 (+
, >
, ~
, 空格),和否定伪类 (:not
) 不会影响优先级。
警告
在进行计算时不允许进行进位,例如,20 个类选择器仅仅意味着 20 个十位,而不能视为 两个百位,也就是说,无论多少个类选择器的权重叠加,都不会超过一个 ID 选择器。
!important
!important
可以用来覆盖所有上面所有优先级计算。
button {
border: none !important;
}
注意
请不要滥用 !important
,只有在不得不使用的情况下再进行使用。
覆盖 !important
唯一的办法就是另一个 !important
具有相同优先级而且顺序靠后,或者更高优先级。