前言
众所周知,CSS 有如下的优先级排序:
!important > 行内元素 > id 选择器 > 类、伪类、属性选择器 > 标签、伪元素选择器 > 通用选择器
那如果多个选择器样式冲突了,以哪个为准呢,之前一直由于实用主义的思想,在能用就行的工作之中并没有深究过这个问题。
优先级
根据MDN文档,CSS 优先级(specificity)如下所示:
以下优先级顺序递增:
- 标签选择器(例如,h1)和伪元素(例如,::before)
- 类选择器(例如,.example),属性选择器(例如,[type=“radio”])和伪类选择器(例如,:hover)
- ID 选择器(例如,#example)。
而通用选择器(*)、关系选择器(combinator)(+、>、~、" "、||)对优先级没有影响。
给元素添加的内联样式(例如,style=“font-weight:bold”)总会覆盖外部的任何样式(当然!important除外)。
!important会覆盖其它所有样式的声明,可以覆盖内联样式,很显然,它具有最高的优先级。
当两个同优先级的样式冲突的时候,生效的是靠后的那一个。
一些例外情况:
:is()和:not()选择器不计算优先级,其括号里面的选择器仍然计算优先级;而:where()选择器,包括它里面的选择器优先级均视为0,也就是不会影响优先级计算。
如何比较优先级
如果几个样式的声明是互相冲突的,写代码的时候我们需要知道到底是谁在生效,不然单纯靠浏览器上面调试太麻烦了。
很显然,!important可以覆盖其它所有样式,内联样式可以覆盖外部样式。同为!important时,比较除了!important外,其它影响 CSS 优先级的因素即可。
比较 CSS 选择器时,我们不妨对于要比较的选择器,记录它们的优先级为的元组(也要考虑上面所说的例外情况)。
- = ID 选择器的数量
- = 类选择器、属性选择器和伪类选择器的数量
- = 标签选择器和伪元素选择器的数量
然后从左到右,即 → → 逐个比较,如果某个样式比较大,则取该样式,相等则比较,再相等则比较,然后得到最高优先级的样式。
像这样子:
html- <button class="my-button" onclick="alert('hello')">Click me</button>
css- .my-button {
- background: blue;
- }
- button[onclick] {
- background: grey;
- }
第一个样式.my-button优先级为。第二个样式button[onclick]优先级为,因此这个按钮的背景是灰色的,蓝色的背景样式就被覆盖掉了。
关于优先级的具体数值
那上面写的5种水平优先级里面,它们事实上的权值是多少,或者说,可不可以用多个低一级选择器(例如类选择器)声明的样式覆盖高一级的选择器(例如 ID 选择器)的呢。
其实不少博客和教程网站,还有一些面经都是说通用选择器权值 0,标签和伪元素为 1,类、属性伪类为 10,ID 为 100,!important为1000(例如web.dev)。
其实事实上两个相邻不同等级选择器权值的差距比这要大得多,在旧版的 IE, Mozilla或 WebKit 的浏览器上, 256 个低一级的选择器(例如类选择器)的权值是等于一个高一级选择器(例如 ID 选择器)的(详见该博客)。
这是由于类选择器个数用 8 字节存储的,超过 255 个就会溢出到 ID 的区域。此外,Opera 浏览器类选择器的存储是 16 字节的。因此,该浏览器要想发生类选择器溢出到 ID 选择器的话,至少需要 65536 个类选择器。
