目录
继承是指把一个元素的某些属性值传给其后代的机制。确定应该把哪些值应用到元素上时,用户代理不仅要考虑继承,还要考虑声明的特指度以及声明的来源,这个过程称为层叠。本章将探讨特指度、继承和层叠之间的关系。后两个概念之间的区别可以像这样简单理解:确定h1{color:red;color:blue}的结果是层叠,把h1中的span显示为蓝色是继承。
特指度
由第二章得知,我们可以使用多种不同的方法选择元素。实际上,同一个元素可能会被两个或多个规则选择,而且每个规则的选择符不尽相同。每对规则中只有一个能胜出。那么,我们如何知道哪个规则胜出呢?
答案隐藏在每个选择符的特指度中。用户代理会计算每个规则中选择符的特指度,然后将其依附到规则中的每个声明上。如果两个或多个属性声明有冲突,特指度最高的声明胜出。
选择符的特指度由选择符本身的组成部分决定。一个特指度值由四部分构成,;例如0,0,0,0选择符的特指度通过下述规则确定:
- 选择符中的每个ID属性值加0,1,0,0。
- 选择符中的每个类属性值、属性选择或伪类加0,0,1,0。
- 选择符中的每个元素和伪类加0,0,0,1。伪类到底有没有特指度,在CSS2中表述的有些自相矛盾。不过CSS2.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*/
在任何情况下,用户代理都会确定哪些规则与元素匹配,然后找出所有相关的声明,计算各自的特指度,判断哪些规则胜出,再把胜出的规则应用到元素上,得到装饰后的结果。每个元素、选择符和声明都要经历这一系列操作。
通用选择符的特指度
通用选择符不增加特指度,而连结选择符根本没有特指度,即连零都没有。因此,连结符对选择符的总特指度没有影响。
ID属性和属性选择符的特指度
ID选择符和选择ID属性的属性选择符之间在特指度上是有区别的。因此,对下述规则来说,id为meadow的元素将显示为绿色:
#meadow {color: green;} /*0,1,0,0*/
*[id="meadow"] {color: red} /*0,0,1,0*/
行内样式的特指度
目前见到的特指度都以零开头,因此你可能在想,那一位为什么要存在呢?存在必定有用,那一位是为行内样式声明保留的。行内样式声明的特指度比其他声明都高。
重要性
有时某个声明可能非常重要,超过其他所有声明。CSS称之为重要声明。这种声明要在声明末尾的分号之前插入!important。例如:
p.dark {color: #333 !important; background: white;}
带有!important的声明对特指度没有影响,但是会与不重要的声明分开处理。其实所有带!important的声明会放在一起,而特指度冲突就在这个范围内解决。同样,非重要的声明作为一个整体,其中的冲突使用特指度解决。因此,重要声明和非重要声明冲突时,重要声明始终胜出。
继承
继承指某些样式不仅应用到所指的元素上,还应用到元素的后代上。
继承是CSS的根基之一,通常无需刻意考虑。不过有几点要留意。
首先,很多属性是不继承的,这通常是为了避免得到意外的结果。例如,border属性(设定元素的边框)就不继承。如果继承边框,文档将变得杂乱无章,除非编写样式时付出额外的精力去掉继承的边框。
此外,基于同样的原因,多数盒模型属性也不继承,包括外边距、内边距、背景和边框。
其次,继承的值没有特指度,连零都没有。
层叠
如果两个特指度相等的规则应用到同一个元素上,会发生什么?浏览器如何解决这样的冲突呢?例如,对下面的规则来说:
h1 {color: red;}
h1 {color: blue;}
哪一个规则胜出?两个规则的特指度都是0,0,0,1,因此它们的权重相同,都应该应用到元素上。但事实并非如此,因为元素的内容不可能既是红色的又是蓝色的,那到底是什么颜色呢?
CSS的层叠规则如下:
- 找到匹配特定元素的所有规则。
- 按显式权重排序应用到特定元素上的所有声明,以!important标记的规则比没有这一标记的权重高。
- 按来源排序应用到特定元素上的所有声明。声明有三个来源,创作人员、读者和用户代理。正常情况下,创作人员编写的样式击败读者提供的样式,读者样式中以!important标记的声明比其他样式权重高,包括创作人员编写的样式中以!important标记的声明;创作人员和读者样式覆盖用户代理的默认样式。
- 按特指度排序应用到特定元素上的所有声明。特指度高的声明具有较高的权重。
- 按声明的前后位置排序应用到特定元素上的所有声明。样式表或文档中靠后的声明权重较高。导入的样式表中的声明放在当前样式表中所有声明的前面。
按权重和来源排序
在声明的权重上,基本要考虑五个方面。下面按权重从高到低列出:
- 读者提供的样式中以!important标记的声明。
- 创作人员编写的样式中以!important标记的声明。
- 创作人员编写的常规声明。
- 读者提供的常规声明。
- 用户代理的默认声明。
创作人员通常只需考虑前四点,因为创作人员编写的任何样式都会覆盖用户代理的默认样式。
按特指度排序
如果应用到一个元素上的声明有冲突,而且各声明的显式权重和来源相同,那么应该按特指度排序,特指度最高的声明胜出。
按前后位置排序
最后,如果两个规则的显式权重、来源和特指度都相同,那么在样式表中的位置靠后的规则胜出。
因为前后位置有影响,所以通常推荐按照一定的顺序编写链接的样式,链接样式的推荐顺序是“link-visited-focus-hover-active”(LVFHA)。
小结
对层叠样式表来说,“层叠”算是最基本的概念。在这个过程中,有冲突的声明按一定顺序排列,由此确定文档的最终表现。这个过程还涉及选择符和与其关联的声明的特指度,以及继承机制。