在我们学习 css 的时候就了解样式优先级的排序是:!important
> 行内样式 > ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性,我们看一下它们到底具体是如何定义的。
css 的样式有三种来源,页面开发者,用户(使用浏览器的人设置的样式),和用户代理(浏览器),这些样式表会在一定的范围内重叠,互相影响页面的最终样式。
当然, css 的层叠规则也指定了不同样式的权重,当这几种规则同时存在的时候,优先级高的规则生效。
样式表层叠顺序
在应用样式之前,会根据媒体查询(
@media
规则)过滤掉一部分样式。需要说明的是,样式的声明包含普通声明和重要声明(就是样式末尾有
!important
)。然后样式的优先级升序排序如下:用户代理声明(浏览器默认,比如按钮的默认样式)
用户常规声明
开发者常规声明
开发者重要声明(
!important
)用户重要声明(
!important
)相同的优先级的样式规则按照选择器的特殊性排序,选择器权重高的将覆盖权重一般的,其中伪元素和伪类被分别算作常规元素和类,具体如何计算在下一节详细说明。
如果选择器的权重一致,则按照声明的顺序排序,后声明的样式覆盖先声明的样式。引入的样式表中的声明被认为在样式表本身的所有声明之前。
这种层叠顺序可以保证了浏览器赋予页面元素默认的初始属性(用户代理声明,优先级最低),同给予了开发者编写比用户和用户代理更高权重样式的能力(开发者声明,优先级高于用户代理和用户常规声明,去掉非用户重要声明的样式),之后又提供了用户强制去除开发者样式的能力(用户重要声明,表达用户强制修改的意愿)。
计算选择器的特殊性
选择器有多个类比,比如标签选择器、类选择器、ID选择器等,不同的选择器有不同的优先级,最终根据优先级计算出样式规则的权重,权重高的覆盖权重低的规则,权重计算如下:
- 如果声明来自内联规则(写在 html 标签的
style
属性内),则计a=1
,否则为a=0
- 计算选择器中 ID 选择器的数量,赋值给
b
- 计算选择器中类选择器、属性选择器和伪类(如
:lang
、:active
)的数量,赋值给c
- 计算选择器中元素名(如
div
、p
)和伪元素(如:before
、:after
)的数量,赋值给d
最后,选择器的权重由 a-b-c-d
决定,a
的优先级最高,a
值相同则比较 b值,以此类推,类似于软件的版本号规则。
看几个示例,优先级从上往下增加:
* {} /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */ |
注意,本节的优先级计算仅在第一节中的声明顺序一致的情况下才有意义,这也是为什么 !important
的优先级最高。