CSS层叠的理解与测试

《CSS权威指南》第3版第三章介绍了关于CSS层叠的原理知识。本文旨在重温与实践在这章节中学到的知识。

首先回忆一下CSS规则的书写方式,如下图所示: CSS规则

接下来对于这章的内容,下面将根据问题熟悉一下知识:

1. 当有同一属性的多个声明作用在同一个html元素的时哪个生效

这里涉及CSS规则声明的特殊性的知识。

多个CSS的规则作用到html元素后,该html元素可能有多个属性相同但值可能不同的声明。每个声明拥有它所在的选择器的特殊性,出现冲突的时候,特殊性高的声明将生效。

特殊性的使用表述为4个部分,形如0,0,0,0。前面的数字越大表示权重越高,如:0,1,0,0权重高于0,0,2,0。

特殊性的计算方法:

  1. 选择器中给定的各个ID属性值,特殊性加0,1,0,0
  2. 选择器中给定的各个类属性值、属性选择或伪类,特殊性加0,0,1,0
  3. 选择器中给定的各个元素、伪属性(CSS2.1包含了伪元素),特殊性加0,0,0,1
  4. 选择器中给定的通配选择,特殊性加0,0,0,0
  5. 选择器中只有结合符没有任何特殊性
  6. 内联样式声明的特殊性为1,0,0,0
  7. 标记了!important的所有重要声明独立归为一组进行计算特殊性从而解决冲突。最终高的生效。

举个例子:

html > body table#t1 tr[id='row1'] td ul > li {color: red}  

这个选择器的特殊性最终为0,1,1,7。因为这个规则的选择器中有1个ID、1个属性选择、7个元素,分别参考计算方法中的前3条,相加等到该值。

对于下面这两个规则:

html > body table tr[id='row1'] td ul > li {color: red}  
li#list1 {color: blue}  

若同时作用在同一个元素li中,那这个li的文本颜色为blue,因为前者特殊性为0,0,1,7;后者特殊性为0,1,0,1。

2. 父元素的声明对子元素有哪些影响

回答这个问题需要考虑CSS继承的概念。

继承

浏览器在解析HTML文档会生成一棵元素树,即所谓DOM树。如下图样例所示: DOM树

如果我们在这棵树中的某个元素A应用了可以继承的属性(如color),那么A元素的所有子节点都将会继承该属性。

PS.

子节点继承父节点的属性不难理解。我们需要关注的是这里的两点特殊性:

首先,有些属性的声明不能够被继承(例如框模型属性,如border、padding、margin等)。因为如果这些属性能够被继承,开发者将需要多做很多工作去消除因继承带来的影响,显然CSS标准考虑到了这个问题。

其次,继承的声明是不具有任何特殊性的(书籍强调:继承的属性甚至连0,0,0,0的特殊性都没有),而0特殊性是比无特殊性的权重更高。我的理解是,如果继承的属性声明具有特殊性,那么特殊性的计算方法将会变得特别复杂。而且这个复杂性对于页面渲染是没有什么利益的。例如有父节点A、子节点B,计算B的某个属性声明的特殊性需要先计算A中出现的特殊性再加自己的特殊性,算法实现起来会困难很多。

3. 相同特殊性的声明哪个生效

这个问题需要考虑的是CSS规则的来源与规则权重。

简单总结下来,CSS层叠的规则如下:

  1. !important标识的规则权重最高
  2. 同等条件下,来源于创作人员的样式 > 读者样式 > 用户代理样式
  3. 特殊性高的规则优先
  4. 后出现的规则会覆盖前面出现的规则

ChardLau

继续阅读此作者的更多文章