Css权威指南(4th,第四版中文翻译)-3.特异性和层级继承

html-css055

Css权威指南(4th,第四版中文翻译)-3.特异性和层级继承,第1张

第2章里面我们了解了document的结构和CSS选择器是如何查找定位对应的元素的。每一个合理的document都会生成一个结构树,基于此,选择器基于元素的祖先,属性,兄弟节点和更多的因素来定位元素。而且这一dom结构树也是CSS种实现继承的基础。

继承是(Inheritance)CSS属性如何从一个元素传递到它的所有子元素的过程。浏览器在决定给一个元素配置什么样式的时候,除了要考虑继承关系,同时也要考虑元素的特异性(Specificity,这个翻译需要斟酌下,但是意思很明显,存在于多个冲突样式中的优先级机制)。而考虑的这一过程就称为级联(cascade)。接下来我们就来探讨一下这三种机制-特异性,继承和级联。后两者的区别其实可以简单归纳为:h1{color:redcolor: blue}的结果就是级联,而在h1中创建一个span就是继承。

综上,别管这几个有多抽象,继续学习,会看到回报的。

从第二章我们看到选组元素的方式太多了,所有很有可能同一个元素被很多规则选中,来看看下面的例子:

上面的3对样式中每对都是作用在同一个元素上,那么到底浏览器该在元素上应用哪一个样式呢?结果就在每个选择规则的特异性中。浏览器逐条评估每条选择器规则的特异性,然后将样式声明应用到元素上。当同一个元素中包含多个存在冲突的属性声明时,有最高特异性的属性就会胜出,把其他冲突规则替换掉。

一个选择器的特异性有选择器的组成决定,而一个特异性的值可以分成4部分,就像这样:0,0,0,0。而真实的特异性是由下面这些决定的:

还是举例来说明吧,分别来看看不同的选择规则对应的特异性值:

既然刚学了如果计算特异性值,赶紧用在之前的例子上吧:

虽然我们一般在写CSS的时候会把多个属性都写在一起,例如:

然而实际上浏览器为了更好的计算特异性值实际会把聚合的属性进行单独的拆分:

咱们再来考虑一个稍微复杂的例子:

基于这个结构最终显示的效果是这样的:

从这个例子中,我们可以很好的看到浏览器按照之前说的特异性的规则展示对应不同值得样式结果。可以看到,浏览器要对每个元素进行拆分,然后计算特异性值后再确定对这个元素渲染那些样式,想想整个流程就很繁杂,幸好浏览器都自动帮我们做好了,而且这是我们后面讲到的级联的很重要的一环。同样,详细了解浏览器的渲染流程也对我们优美的书写CSS样式有很大助益。

通用选对特异性值是没有贡献的,但它是有值的,虽然值是0,0,0,0,但这和没有特异性值是有区别的,后面会在继承章节中详细讨论。所以下面的结果是显而易见的:

除了div的后代p显示为黑色外,其他都显示为灰色。而通用选择器是不贡献特异性值得,因此下面两个表达式的值也是一样的:

之前有提过直接的ID选择器和通过属性选择器设置ID值,他们最终计算的特异性值是不同的。我们先回到之前的一个例子:

因为直接用ID选择器贡献的特异性值为0,1,0,0,而属性贡献的值为0,0,1,0, 所以下面的结果也是显而易见的:

到现在肯定很多读者会想,之前计算的特异性值的4位里面第一位是什么时候设置的?答案就是为内联样式设计的,比其他的所有声明优先级都高。来看看下面的例子:

结果很明显h1就是绿的,因为内联样式的值更高,或者说优先级更高。

有时候特异性值更高的样式还并不是你想要的,这时候可使用!important来表示那些特别重要的样式,不过格式有严格的规定,就是必须在分号前面加,例如:

!important表达式必须正确,不然的话会报错。那如果存在对同一个样式有多个important声明会怎样呢?那么这些样式都不会被应用,所以需要保证important的唯一性。

其实浏览器是这么处理important样式和非important样式的:将它们单独分成两拨,important的一拨优先级更高,并且在这个组内处理自身的冲突啥的;同样的逻辑对应于非important组,组内采用特异性值来解决冲突。来看个例子:

继承,顾名思义就是属性在祖先-后代节点间的传递机制。比如说一个在h1标签中设定的颜色,那么h1中的所有后代文本都会继承。

上例中em就是继承了h1中的gray颜色。来看个ul标签的例子:

可以看到ul的所有li元素也都继承了这一特性。继承看似简单不过也需要注意几点:

有没有很意外em中的元素为啥还是灰的,照理说应该都是黑色才对,就是因为继承来的黑色属性没有特异性值,而被全局的样式给替换了。

有时候没有特异性值也会带来麻烦,比如看:

如果id=toolbar的元素下面有链接,那么就很有可能因为没有定义而采用浏览器的默认样式,一般来说是这样:

解决方案归根结底还是要有特异性值,可以有多种方法都是可以的:

再来考虑下个问题,如果两个具有完全相同特异性值的元素作用在同一个节点上,那该怎么办?比如说像这样:

还记得css为啥叫css么?Cascading Style Sheet,级联样式表,通过定义相关的规则来结合继承和特异性值。来看看都有哪些吧。

为了更好理解,我们对后四个规则进行详细说明:

虽然p本身有内联的样式,但因为标记了!important,所以还是显示为灰色。另外即使给内联样式加上了important也没啥用:

在上面权重相同的情况下对比源头,作者的优先级高于读者的。但如果在important情况下,读者的优先级要高于作者的,总结一下顺序就是:

如果上面的类型相同,则会进入到这一步,判断特异性值。

如果特异性值也一致,最后判断下出现的顺序,后出来的覆盖先前的。

结果就是blue颜色。而这一顺序对import进来的样式也是一样的。

而就是因为这个原因才会有链接推荐样式的顺序方案,一般称为LVFHA,就像下面这样:

这个顺序还可以有另一种玩法,实现的效果是只有未访问的链接才会有hover样式,而且所有链接都会有active样式,就像下面这样:

不过最好的办法就是使用串联的伪类来彻底消除这种情况,为不同的状态设定不同的样式:

不过如果引入了active类的话还是会触发冲突:

如果我们把最后两个active状态移到hover前面,那么它们就会被忽略,当然也是有办法解决的,就是引入更多的伪类:

可能对CSS来说最基本的就是本章所讲的级联机制本身,如何解决冲突,如何实现继承,如何实现排序,都有一套底层的规则在作用。

第一种 和第二种 的原理是一样的。所以速度是一样的。

第3种属于内部调用,速度最快。但是不标准。

给说下 调用的理论。

浏览器解释是逐句解释。遇见 先解释标签,然后标签属性。

第一二种的原理是一样的,

1.浏览器遇见 div标签以后 解释好;

2.然后解释他的CLASS属性,解释CSS属性的值是1个(2个)类名;

3.然后查询事先预载好的<style>标签里的属性;

4.然后赋给<DIV>标签。

5.读取赋值后的属性显示内容。

第三种的原理,

1.浏览器遇见 div标签以后 解释好;

2.然后解释他的style属性;

3.直接读取style属性 显示。

但是建议你使用前一种原理,不经这种熟读不在考虑范围之内,就算再大的网站也不会占用太多的速度。理论上说三种速度最宽,但是现实中 前2种是最好最实用的。