CSS权威指南(第四版)笔记 (第三章:优先级和层叠)

578 阅读5分钟

第三章:优先级和层叠

3.1 优先级

优先级就是分配给指定的CSS声明的一个权重,由选择器的本身组成决定,一个优先级由4部分构成,例如(0, 0, 0, 0)。

选择器的优先级有以下规则:

  1. ID选择器为0, 1, 0, 0
  2. 类选择器,属性选择器,伪类为0, 0, 1, 0
  3. 每个元素选择器,伪元素为0, 0, 0, 1
  4. 连接符和通配选择器不增加优先级(通配选择器的优先级为0, 0, 0, 0,而连接符没有优先级)。
  5. 行内样式的优先级为1, 0, 0, 0

比如:

h1 {color: red;} /* 优先级 = 0, 0, 0, 1 */
p em {color: red;} /* 优先级 = 0, 0, 0, 2 */
.warning {color: red;} /* 优先级 = 0, 0, 1, 0 */
*.warning.up {color: red;} /* 优先级 = 0, 0, 2, 0 */
div#main {color: red;} /* 优先级 = 0, 1, 0, 1 */
div#main *[href] {color: red;} /* 优先级 = 0, 1, 1, 1 */

如果两个或多个属性声明有冲突,那么优先级高的会胜出。

em {color: red;} /* 优先级 = 0, 0, 0, 1 */
p em {color: red;} /* 优先级 = 0, 0, 0, 2 (胜出)*/

声明和优先级

选择器的优先级确定后,将被赋予关联的每个声明。

比如:

h1 {
    color: red;
    backgroud: black;
}
/* 将被视为: */
h1 {color: red;}
h1 {backgroud: black;}

如果多个规则匹配同一个用啥,那么优先级就起作用了。

比如:

h1 + p {color: red;}/* 优先级 = 0, 0, 0, 2 */
.side{color: green;}/* 优先级 = 0, 0, 1, 0 */
p{color: blue;}/* 优先级 = 0, 0, 0, 1 */

对于文档:

<h1>这个是h1</h1>
<p class='side'>这是一个段落</p>

结果为:

优先级

通配选择器和连接符的优先级

通配选择器优先级为0, 0, 0, 0,连接符不存在优先级。

ID选择器和属性选择器的ID属性的优先级

ID选择器和属性选择器的ID属性的优先级是不同的,ID选择器的优先级为0, 1, 0, 0;而属性选择器的ID属性的优先级为0, 0, 1, 0

行内样式的优先级

行内样式的优先级为1, 0, 0, 0,所有行内样式具有最高的优先级。

例外的 !important 规则

当在一个样式声明中使用一个!important 规则时,此声明将覆盖任何其他声明。虽然技术上!important与优先级无关,但它与它直接相关。

比如:

h1 + p {color: red;}/* 优先级 = 0, 0, 0, 2 */
.side{color: green;}/* 优先级 = 0, 0, 1, 0 */
p{color: blue !important;}/* 优先级 = 0, 0, 0, 1 */

对于文档:

<h1>这个是h1</h1>
<p class='side'>这是一个段落</p>

结果为:

!important规则

3.2 继承

继承指某些样式不仅应用到所指的元素,还应用到元素的后代上。

在CSS中,每个CSS属性定义的概述都指出了这个属性是默认继承的(“Inherited: Yes”) 还是默认不继承的(“Inherited: no”)。这决定了当你没有为元素的属性指定值时该如何计算值。

继承是CSS的根基之一,哪些属性默认被继承哪些不被继承大部分符合常识,通常无需考虑。但是需要注意的是:

继承的值没有优先级。(所以继承属性和通配选择器有冲突时候,通配选择器胜出)。

比如以下CSS设置:

* {color: red;}
h1#title {color: black;}

对于文档:

<h1 id="title">
    h1标题<em>倾斜的em</em>
</h1>

结果为:

继承的值没有优先级

3.3层叠

层叠是CSS的一个基本特征,它是一个定义了如何合并来自多个源的属性值的算法。它在CSS处于核心地位,CSS的全称层叠样式表正是强调了这一点。

CSS声明可以有不同的来源:

  • 浏览器会有一个基本的样式表来给任何网页设置默认样式。这些样式统称用户代理样式
  • 网页的作者可以定义文档的样式,这是最常见的样式表。
  • 读者,作为浏览器的用户,可以使用自定义样式表定制使用体验。

层叠规则

  1. 首先过滤来自不同源的全部规则,并保留要应用到指定元素上的那些规则。

  2. 依据重要性对这些规则进行排序。即是指,规则后面是否跟随者!important以及规则的来源。层叠是按升序排列的,这意味着来着用户自定义样式表的!important值比用户代理样式表的普通值优先级高:

    重要性(从低到高) 来源 重要程度
    1 用户代理 普通
    2 用户代理 !important
    3 用户 普通
    4 页面作者 普通
    5 CSS动画 见下节
    6 页面作者 !important
    7 用户 !important
  3. 假如层叠顺序相等,则使用哪个值取决于优先级。

CSS动画与层叠

CSS动画,指使用@keyframes @规则定义状态间的动画。关键帧不参与层叠,意味着在任何时候CSS都是取单一的@keyframes的值而不会是某几个@keyframe的混合。

当有多个满足条件的关键帧时,在最重要的文档里面最后定义的关键帧会被选中,而不会是将它们组合在一起。

同时仍应注意用@keyframes @规则定义的值会覆盖全部普通值,但会被!important的值覆盖。

例子

用户代理CSS:

li { margin-left: 10px }

网页作者CSS1:

li { margin-left: 0 } 

网页作者CSS2:

@media screen {
  li { margin-left: 3px }
}

@media print {
  li { margin-left: 1px }
}

用户CSS:

.specific { margin-left: 1em }

HTML:

<ul>
  <li class="specific">1<sup>st</sup></li>
  <li>2<sup>nd</sup></li>
</ul>

对于这个情形,应当应用li.specific里面的声明。由于没有声明被标记为!important,所以优先顺序为页面作者样式优于用户样式,用户代理样式最低。

故是这3条声明的竞争:

margin-left: 0
margin-left: 3px
margin-left: 1px

由于是在屏幕显示,所以最后一条舍弃,而前两条的选择器相同,因此优先级也相同,故最终选择的是后者:

margin-left: 3px

注意尽管定义在用户CSS里面的声明有更高的优先级,但它并不会被选中,因为层叠算法是先于优先级算法的。