CSS权威指南(第四版)读书笔记——第3章 特指度和层叠之特指度

前端技术 everyinch 1409℃ 0评论

由第2章得知,我们可以使用多种不同的方法选择元素。实际上,同一个元素可能会被两个或多个规则选择,而且每个规则的选择符不尽相同。

h1 {color: red;}

body h1 {color: green;}

h2.grape {color: purple;}

h2 {color: silver;}

 

html > body table tr[id=”totals”] td ul > li {color: maroon;}

li#answer {color: navy;}

每对规则中只有一个能胜出,因为匹配的元素只能显示为其中一个颜色。那么我们如何知道哪个规则胜出呢?

答案隐藏在每个选择符的特指度中。用户代理会计算每个规则中选择符的特指度,然后将其依附到规则中的每个声明上。如果两个或多个属性声明有冲突,特指度最高的声明胜出。

选择符的特指度由选择符本身的组成部分决定。一个特指度值由四部分构成,例如0,0,0,0。选择符的特指度通过下述规则确定:

  1. 选择符中的每个ID属性值加0,1,0,0。
  2. 选择符中的每个类属性值、属性选择或伪类加0,0,1,0。
  3. 选择符中的每个元素和伪元素加0,0,0,1。伪类到底有没有特指度在CSS2中表述的有些自相矛盾,不过1明确指出,伪元素有特指度。
  4. 连结符和通用选择符不增加特指度。

例如,下面给出几个规则中选择符的特指度:

h1 {color: red;}          /* specificity = 0,0,0,1 */

p em {color: purple;}     /* specificity = 0,0,0,2 */

.grape {color: purple;}   /* specificity = 0,0,1,0 */

*.bright {color: yellow;} /* specificity = 0,0,1,0 */

p.bright em.dark {color: maroon;} /* specificity = 0,0,2,2 */

#id216 {color: blue;}         /* specificity = 0,1,0,0 */

div#sidebar *[href] {color: silver;} /* specificity = 0,1,1,1 */

现在做一个练习,计算本节开头那几对规则的特指度:

h1 {color: red;}          /* 0,0,0,1 */

body h1 {color: green;}   /* 0,0,0,2 (winner)*/

h2.grape {color: purple;}   /* 0,0,1,1 (winner) */

h2 {color: silver;}         /* 0,0,0,1 */

html > body table tr[id=”totals”] td ul > li {color: maroon;} /* 0,0,1,7 */

li#answer {color: navy;}                          /* 0,1,0,1  (winner) */

 

我已经指出每一对中的胜者,即特指度较高的规则。注意特指度的比较方式。在第二对中,h2.grape选择符胜出,因为它多一个1,0,0,1,1大于0,0,0,1。在第三对中,后一个规则胜出,因为0,1,0,1大于0,0,1,7。特指度值0,0,1,0其实比0,0,0,13大。

3.1.1声明和特指度

选择符的特指度确定之后,其值将赋予关联的每个声明。对下述规则来说:

h1 {color: silver; background: black;}

为了计算特指度,用户代理必须把规则“打散”成单独的规则。因此,上述规则将变成:

h1 {color: silver;}

h1 {background: black;}

二者的特指度都是0,0,0,1,赋予每个声明的值就是它。群组选择符也有这样的打散过程。对下述规则来说:

h1, h2.section {color: silver; background: black;}

在用户代理看来是这样的:

h1 {color: silver;}              /* 0,0,0,1 */

h1 {background: black;}    /* 0,0,0,1 */

h2.section {color: silver;} /* 0,0,1,1 */

h2.section {background: black;} /* 0,0,1,1 */

如果多个规则匹配同一个元素,而且部分声明之间有冲突,特指度就发挥作用了。例如,对下面的规则来说:

h1 + p {color: black; font-style: italic;}               /* 0,0,0,2 */

p {color: gray; background: white; font-style: normal;} /* 0,0,0,1 */

*.aside {color: black; background: silver;}              /* 0,0,1,0 */

应用到下述标记后渲染得到的结果如图3-1所示。

<h1>Greetings!</h1>

<p class=”aside”>

It’s a fine way to start a day, don’t you think?

</p>

<p>

There are many ways to greet a person, but the words are not as important as the act of greeting itself.

</p>

<h1>Salutations!</h1>

<p>

There is nothing finer than a hearty welcome from one’s fellow man.

</p>

<p class=”aside”>

Although a thick and juicy hamburger with bacon and mushrooms runs a close second.

</p>

图3-1:不同规则对文档的影响

在任何情况下,用户代理都会确定哪些规则与元素匹配,然后找出所有相关的声明,计算各自的特指度,判断哪些规则胜出,再把胜出的规则应用到元素上,得到装饰后的结果。每个元素、选择符和声明都要经历这一系列操作。幸好,用户代理能自动处理一切。这个行为是层叠的重要部分。

3.1.2通用选择符的特指度

通用选择符不增加特指度。也就是说,它的特指度为0,0,0,0,这与没有特指度是不同的(参见3.2节)。因此,对下面两个规则来说,div元素中的段落将显示为黑色,其他元素则显示为灰色:

div p {color: black;} /* 0,0,0,2 */

* {color: gray;}       /* 0,0,0,0 */

你可能猜到了,包含通用选择符的选择符,它的特指度不因有通用选择符的存在而改变。下面两个选择符的特指度相等:

div p          /* 0,0,0,2 */

body * strong /* 0,0,0,2 */

连结符不同,它根本没有特指度,即连零都没有。因此,连结符对选择符的总特指度没有影响。

3.1.3 ID和属性选择符的特指度

ID选择符和选择id属性的属性选择符之间在特指度上是有区别的,这一点一定要注意。来看前述示例中的第三对规则:

html > body table tr[id=”totals”] td ul > li {color: maroon;} /* 0,0,1,7 */

li#answer {color: navy;}                          /* 0,1,0,1 (wins) */

第二个规则中的ID选择符(#answer)为选择符的总特指度贡献0,1,0,0。然而,第一个规则中的属性选择符([id=”totals”])为总特指度贡献0,0,1,0。因此,对下述规则来说,id为meadow的元素将显示为绿色:

#meadow {color: green;}       /* 0,1,0,0 */

*[id=”meadow”] {color: red;} /* 0,0,1,0 */

3.1.4行内样式的特指度

目前见到的特指度都以零开头,因此你可能在想,那一位为什么要存在呢?存在必定有用。那一位是为行内样式声明保留的,行内样式声明的特指度比其他声明都高。对下面的规则和标记片段来说:

h1 {color: red;}

<h1 style=”color: green;”>The Meadow Party</h1>

即便那个规则会应用到h1元素上,但是h1元素中的文本仍将显示为绿色。这是因为行内声明的特指度为1,0,0,0。

3.1.5重要性

有时某个声明可能非常重要,超过其他所有声明。CSS称之为重要声明(important declaration,原因显而易见)。这种声明要在声明末尾的分号之前插入!important,例如:

p.dark {color: #333 !important; background: white;}

这里,颜色值#333使用!important标记,而背景色white没有。如果想把两个声明都标记为重要的,每个声明中都要插入!important:

p.dark {color: #333 !important; background: white;}

!important的位置必须正确,否则声明将失效。!important始终放在声明末尾的分号之前。对值为多个关键字的属性(例如font)来说,!important的位置尤其重要:

p.dark {color: #333 !important; background: white !important;}

带有!important的声明对特指度没有影响,但是会与不重要的声明分开处理。其实,所有带 !important的声明会放在一起,而特指度冲突就在这个范围内解决。同样,非重要的声明作为一个整体,其中的冲突使用特指度解决。因此,重要声明和非重要声明冲突时,重要声明始终胜出。

下述规则和标记片段的结果如图3-2所示。

h1 {font-style: italic; color: gray !important;}

.title {color: black; background: silver;}

* {background: black !important;}

<h1 class=”title”>NightWing</h1>

图3-2: 重要规则始终胜出

分享&收藏

转载请注明:陈童的博客 » CSS权威指南(第四版)读书笔记——第3章 特指度和层叠之特指度

喜欢 (3)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
'; } if( dopt('d_footcode_b') ) echo dopt('d_footcode'); ?>