也许你也有经历过这样的情况:明明自己已经为某个元素指定了一条 CSS 规则了,怎么在浏览器中显示出来的却跟期望的相差很多呢?你是否有仔细研究过这里面的问题?你是否有了解到 CSS 样式的优先级算法?如果没有,那么可以请接下来看看我对 CSS 优先级算法的一个讲解吧。
在开始之前:
我们先来了解一下 CSS 选择器都有哪些:
- 通配选择符:
* { SRule }
,如:
* {
font-size: 14px;
}
- 类型选择符:
element { sRule }
,如:
div {
background: #000000;
}
- 属性选择符:
element[attr] { sRule }
、element[attr=value] { sRule }
、element[attr~=value] { sRule }
、element[attr|=value] { sRule }
,如:
h1[title] {
font-size: 20px;
}
input[type='text'] {
font-size: 14px;
}
- 包含选择符:
parent child { sRule }
,如:
div span {
font-size: 14px;
}
- 子元素选择符:
parent > child { sRule }
,如:
div>span {
font-size: 14px;
}
- ID 选择符:
#id { sRule }
,如:
#name {
font-size: 14px;
}
- 类选择符:
.class { sRule }
,如:
.btn {
background: #000000;
}
- 伪类:
:link、:visible、:hover、:active、:focus、:first-child
。 - 伪元素:
:before、:after、:first-line、:first-letter
CSS Specificity
讲完了 CSS 的各种选择符之后我们来看看究竟是什么决定了一个元素最终的显示效果。总的来说,浏览器是根据元素的 CSS Specificity 的值的大小来决定每个元素最终应该应用哪些规则的。
The Concept
Specificity is the means by which a browser decides which property values are the most relevant to an element and gets to be applied. Specificity is only based on the matching rules which are composed of selectors of different sorts.—— 摘自 MDN
CSS Specificity 是 CSS 样式层叠中最难理解的一个部分。通常来说不同的选择器权重就是你的 CSS 规则与期望的不一致的原因。为了彻底理解浏览器是如何为每个元素应用规则的,你必须深刻理解 CSS Specificity 的概念,并且懂得计算它。这也是这篇文章标题所说的,了解 CSS 的优先级算法。
CSS Specificity 概览
- Specificity 决定浏览器应该应用哪些CSS规则于元素中。
- Specificity 通常就是为什么你的 CSS 规则不应用于某些元素中的原因,尽管你认为它应该是会应用于这些元素的。
- 每个选择符都有它自己的 Specificity 层级权重。
- 如果为同一个元素应用了两条规则,则具有更高 Specificity 权重的规则胜出。
- 有四种很直观具有不同的 Specificity 权重的类别,分别是: 行内样式,ID 选择符,类选择符和属性选择符, 还有元素选择符。
- 如果有多个选择符具有相同的 Specificity 值,那么最后出现的规则胜出。
- 如果有多个选择符具有不同的 Specificity 值,那么更加具体的规则具有更高的 Specificity 值。
- 最后定义的规则会覆盖前面冲突的规则。
- 内联样式相比其他规则具有更高的 Specificity 值。
- ID 选择符比属性选择符具有更高的 Specificity 值。
- 如果想要增加一个元素的 Specificity 值,你应该尝试使用 ID 选择符。
- 一个类选择符比无论多少个元素选择符都拥有更高的 Specificity 值。
- 你可以使用 CSS Specificity 计算器来计算 CSS 的 Specificity 。
如何计算 CSS Specificity
- 记住如何计算 CSS Specificity。 从 0 开始,内联样式加 1000,每个 ID 选择符样式加 100 ,每个类选择符样式或者属性选择符样式或者伪类选择符加 10 , 每个元素选择符或者伪元素选择符加 1 。如:
body #content .data img:hover { }
以上规则的 CSS Specificity 值是122(或者 0,1,2,2 或者 0122)
。计算过程:0 + 100 (#content ID 选择符) + 10 (.data 类选择符)+ 10 (:hover 伪类选择符) 1 (body 元素选择符)+ 1 (img 元素选择符) + = 122
- 其他方法: Selector Specificity
一些练习
以上内容大致介绍了 CSS Specificity 和它的计算方法。其中有一些需要注意的是,使用通配符定义的样式规则其 CSS Specificity 值为 0,0,0,0 ,通过继承的样式规则的 CSS Specificity 值也为 0,0,0,0。而使用
!important
定义的规则具有最高的 CSS Specificity 。至此,关于浏览器是如何渲染一个元素的样式的这个问题应该不再是难题。
总而言之,
!important
具有最高优先级。行内样式比外部CSS文件的规则优先级更高。ID 选择符的样式比类选择符和属性选择符和伪类选择符的优先级更高,而类选择符和属性选择符和伪类选择符的规则优先级又比元素选择符和伪元素选择符规则更高。通配符规则和继承的规则的优先级最低。最后出现的规则会覆盖前面的冲突的规则。更详细的规则拥有更高的优先级。可以通过计算 CSS Specificity 的值来判断浏览器应该渲染哪些规则。