css又叫层叠样式表,层叠机制是css最基本的机制。
页面中的的每个html元素,都具有一整套css属性,每个css属性有且只有唯一值。
我们可以把每个元素看成一个盒模型,css属性用来描绘这个盒模型的性质、形状、位置、内容、背景颜色等等。
我们可以在开发者工具的Computed栏下看到每个元素的盒模型以及所有css属性值:

以上这些css属性值是解析器通过计算后得到的,网页会拿这个结果去排列页面中形形色色的元素盒子(布局
)。
而这些属性最初有两个基本来源:开发者定义的和浏览器默认自带的,前者又叫作者样式表 ,后者又叫浏览器默认样式表 或者叫用户代理样式表(user agent stylesheet),浏览器也被称为用户代理,是因为它代表用户向服务器发送请求。
其实还有一个来源是用户样式表,即网站访问者通过开发者工具操作css样式,这种情况具有最高优先权,一般在调试的时候才会用到,本文就不做详细讨论了。
可以在开发者工具的Styles栏下看到元素的原始css属性值:
不难发现,元素的每个css属性都有多个来源,但是最终只有一个值会参与网页绘制,所以,css的属性有个计算过程,而这可以大致分为四个步骤:(1) 确定声明值 (2) 层叠冲突 (3) 使用继承 (4) 使用默认值。
1.确定声明值
第一步会把来自作者样式表和浏览器默认样式表的所有css属性值进行汇总 ,汇总的好处在于,一是避免遗漏,二是方便处理。
2.层叠冲突
因为css属性来源不同,必然有些是会冲突的,这一步就是解决掉那些冲突的样式,根据优先级规则把多余的属性删除,只留下一个属性。
可以看到浏览器中这些划掉的属性,就是那些多余的冲突了的属性:
那么应该删除哪些属性,保留哪个属性呢?这还需要对诸多属性进行比较,它们将按照如下顺序进行:
-
先比较重要性
带有important的作者样式 > 带有important的默认样式 > 作者样式 > 默认样式
强烈建议除了非常情况不要使用important,它改变了层叠的常规工作方式,会使调试变得困难,特别是在大型样式表中!
-
当重要性相同时,再比较特殊性(即权重),不同的样式引入方式或者不同的选择器,都会影响它的权重
- style:内联样式优先于所有普通的样式
- id选择器:id选择器的数量
- 属性选择器:属性、类、伪类选择器的数量
- 元素选择器:元素、伪元素选择器的数量
以上四种都有它自己的优先级等级,它们不会被具有较低优先级的选择器覆盖。例如,权重为一百万的类选择器不会覆盖权重为一的 ID 选择器。
评估优先级的最佳方法是对不同的优先级等级单独进行评分,并从最高的等级开始,必要时再计算低优先级等级的权重。即,仅当某一列的优先级权重相同时,你才需要评估下一列;否则,你可以直接忽略低等级的选择器,因为它们无法覆盖高优先级等级的选择器。
-
当样式声明同源,且权重也相同,会比较样式声明的次序,即后面的会覆盖前面的
如此三步之后,凡是冲突的属性,最后都会只剩下唯一值。
3.使用继承
除了冲突的属性,那些未冲突的属性,也得有值。
所以,对网页作者和浏览器都没有赋值的属性,若可以继承,则继承父元素的值 。通常,可以通过常识
来判断哪些属性可以继承。
4.使用默认值
最后,网页作者和浏览器都没有给属性赋值,且也无法继承的属性,会使用默认值(每个属性都会有的)。
此外,还需注意的是,鉴于 css 一直不断的开发,因此领先于浏览器可以识别的范围,那么当浏览器遇到无法解析的 css 选择器或声明的时候会发生什么呢?
答案是浏览器什么也不会做,继续解析下一个 css 样式!
在你书写了错误的 css 代码(或者误拼写),又或者当浏览器遇到对于它来说很新的还没有支持的 css 代码的时候上述的情况同样会发生(直接忽略)。
总结一下:
每个html元素都有一套css属性,每个css属性有且只有一个值。
浏览器经过四个非常明确定义的步骤来确定每个元素的每个属性的值:(1) 确定声明值 (2) 层叠冲突 (3) 使用继承 (4) 使用默认值。
浏览器会忽略掉错误的css选择器或者属性和值,继续解析下一个css样式。