层叠

CSS全称就叫cascading style sheets,层叠样式表,所以层叠这个概念是很重要的。
先来介绍一个概念,声明冲突:同一个样式多次应用到了同一个元素。
我们自己写的CSS代码可能会和浏览器的CSS样式有冲突:

a{  
    color: red;
}

声明冲突不一定是坏事,实际网站开发中甚至往往用到声明冲突,如:

span{  
    color: red;
} 
.selected{
    color: #fff;
    background-color: red;
}
<body>
    <span>Lorem.</span>
    <span>Quae.</span>
    <span>Aut!</span>
    <span class="selected">Minus.</span>
    <span>Vel.</span>
    <span>Sint?</span>
    <span>Quibusdam?</span>
    <span>Dolorem.</span>
</body>


这种样式是不是很熟悉?像下面这张截自百度贴吧的图就应用了这种样式:

这种应用就是绝大部分元素的样式一样,只有其中某些元素处于特殊的状态(比如鼠标悬停)就更改样式。

解决声明冲突的过程就叫层叠
层叠不是由我们解决的,是由浏览器自动处理的,我们要学习的就是浏览器如何处理这个冲突过程的。
层叠也有很多其他叫法,比如权重计算。它一共经过三步:

  1. 比较重要性
  2. 比较特殊性
  3. 比较原次序

经过这三个步骤之后,最后一定只有一个样式胜出,元素就应用那个胜出的样式。
下面逐个介绍。


1.比较重要性

比较重要性时考虑的因素很多,没必要全都了解。
主要的三个重要性排序为:

1)作者样式表中的!important样式
作者样式表就是开发者书写的样式,包括html文档中的<style>、css文件中的样式等。
我们写代码时可以在样式后面加上!important,如

span{  
    color: red !important;
} 

这样就表示这个样式是重要性最高,最后一定会胜出,被应用。
所以这种方法太绝对了,如果哪天网站需求改变了,就很难更改,所以应用得极少。

2)作者样式表中的普通样式

3)浏览器(用户代理)默认样式表中的样式


2.比较特殊性

当比较重要性结束之后冲突还没有解决,就继续进行比较特殊性这一步骤。
总体规则:看选择器,选择器定位的范围越窄就越特殊。
具体规则:通过选择器计算一个4位十进制数,也就是权重,这个数越大就越特殊。

1)千位
如果是内联样式,千位为1,否则为0。 所以内联样式最特殊,优先级最高。
浏览器的在线调试就是使用的内联样式。

2)百位
等于选择器中所有ID选择器的数量。

3)十位
等于所由选择器中类选择器、伪类选择器、属性选择器的数量。

4)个位
等于选择器中元素选择器、伪元素选择器的数量。
比如a{ ... }的权重是0001,body a{ ... }的权重是0002,所以后者胜出。

举例:
html:

<div id="mydiv">
    <ul id="myul">
        <li id="myli">
            <a href="https://douban.com" class="mylink">
                Lorem ipsum dolor sit amet.
            </a>
        </li>
    </ul>
</div>

css:

a{
    color: red;
}
div ul a{
    color: green;
}
#mydiv #myul a{
    color: blueviolet;
}
#mydiv #myul .mylink{
    color: gold;
}
#mydiv #myul a:link{
    color: chocolate;
}

首先这几个都是作者样式表,所以他们的重要性是一样的,接下来比较特殊性,计算权重。
它们都不是内联样式,所以千位都为0。
a{ ... }的权重是0001
div ul a{ ... }的权重是0003
#mydiv #myul a{ ... }的权重是0201
#mydiv #myul .mylink{ ... }的权重是0210
#mydiv #myul a:link{ ... }的权重是0211
所以最后者胜出,网页文字被渲染为了chocolate色:

补充:这里的权重四位数不是逢十进一的,而是逢256进一。所以这里的“四位数”是应该加引号的,它本质上是四个数字,从高到低一个个数字比较。


3.比较源次序

当然权重值是完全有可能相同的,所以这时要解决冲突就要继续向下比较,即比较源次序:代码书写靠后的胜出。
可以用栈的思维去助记:后进先出,最后读的代码就是最新的,就会被应用。
这步比完之后就肯定会揭晓胜负了,不存在平局。


层叠应用

1)重置样式表
不同浏览器的默认差异是有差异的,所以就导致你写的网页在不同浏览器上显示各异。这时可以书写一些作者样式,覆盖浏览器的默认样式。
实际项目中应用重置样式表的思想时,往往会创建reset.cssmystyle.css两个css文件,前者用来通用地重置,后者用来书写自己实际开发要用到的样式。然后在html文件中加入:

<link rel="stylesheet" href="./css/reset.css">
<link rel="stylesheet" href="./css/mystyle.css">

这样由于源次序规则,就会先应用自己写的mystyle.css样式。
重置样式的书写方法差不多是固定的,可以去网络上download下来,如normallize.cssreset.cssmeyer.css等。
比如可以在meyerweb.com找到相应的css文件,使用绝对地址引用。

2)爱恨法则
对于超链接,要按linkvisitedhoveractive的相对顺序书写,love、hate,即“爱恨法则”。
为什么是这个顺序呢?因为这样才符合人的意愿。同一个时刻可能有多个状态都符合条件,比如鼠标按下激活(active)时也符合了鼠标悬停(hover)的状态,那么这个时候我们希望的肯定是鼠标按下的状态。所以基于人们的意愿就形成了爱恨法则这样的次序。