coverPiccoverPic

关于 CSS 优先级的那些事

前言

众所周知,CSS 有如下的优先级排序:

!important > 行内元素 > id 选择器 > 类、伪类、属性选择器 > 标签、伪元素选择器 > 通用选择器

那如果多个选择器样式冲突了,以哪个为准呢,之前一直由于实用主义的思想,在能用就行的工作之中并没有深究过这个问题。

优先级

根据MDN文档,CSS 优先级(specificity)如下所示:

以下优先级顺序递增:

  1. 标签选择器(例如,h1)和伪元素(例如,::before)
  2. 类选择器(例如,.example),属性选择器(例如,[type=“radio”])和伪类选择器(例如,:hover)
  3. ID 选择器(例如,#example)。

通用选择器(*)、关系选择器(combinator)(+、>、~、" "、||)对优先级没有影响。

给元素添加的内联样式(例如,style=“font-weight:bold”)总会覆盖外部的任何样式(当然!important除外)。

!important会覆盖其它所有样式的声明,可以覆盖内联样式,很显然,它具有最高的优先级。

当两个同优先级的样式冲突的时候,生效的是靠后的那一个。

一些例外情况::is():not()选择器不计算优先级,其括号里面的选择器仍然计算优先级;而:where()选择器,包括它里面的选择器优先级均视为0,也就是不会影响优先级计算。

如何比较优先级

如果几个样式的声明是互相冲突的,写代码的时候我们需要知道到底是谁在生效,不然单纯靠浏览器上面调试太麻烦了。

很显然,!important可以覆盖其它所有样式,内联样式可以覆盖外部样式。同为!important时,比较除了!important外,其它影响 CSS 优先级的因素即可。

比较 CSS 选择器时,我们不妨对于要比较的选择器,记录它们的优先级为(a,b,c)(a, b, c)的元组(也要考虑上面所说的例外情况)。

  1. aa = ID 选择器的数量
  2. bb = 类选择器、属性选择器和伪类选择器的数量
  3. cc = 标签选择器和伪元素选择器的数量

然后从左到右,即aabbcc逐个比较,如果某个样式aa比较大,则取该样式,相等则比较bb,再相等则比较cc,然后得到最高优先级的样式。

像这样子:

html
  1. <button class="my-button" onclick="alert('hello')">Click me</button>
css
  1. .my-button {
  2. background: blue;
  3. }
  4. button[onclick] {
  5. background: grey;
  6. }

第一个样式.my-button优先级为(0,1,0)(0, 1, 0)。第二个样式button[onclick]优先级为(0,1,1)(0, 1, 1),因此这个按钮的背景是灰色的,蓝色的背景样式就被覆盖掉了。

关于优先级的具体数值

那上面写的5种水平优先级里面,它们事实上的权值是多少,或者说,可不可以用多个低一级选择器(例如类选择器)声明的样式覆盖高一级的选择器(例如 ID 选择器)的呢。

其实不少博客和教程网站,还有一些面经都是说通用选择器权值 0,标签和伪元素为 1,类、属性伪类为 10,ID 为 100,!important为1000(例如web.dev)。

其实事实上两个相邻不同等级选择器权值的差距比这要大得多,在旧版的 IE, Mozilla或 WebKit 的浏览器上, 256 个低一级的选择器(例如类选择器)的权值是等于一个高一级选择器(例如 ID 选择器)的(详见该博客)。

这是由于类选择器个数用 8 字节存储的,超过 255 个就会溢出到 ID 的区域。此外,Opera 浏览器类选择器的存储是 16 字节的。因此,该浏览器要想发生类选择器溢出到 ID 选择器的话,至少需要 65536 个类选择器。

0 条评论未登录用户
Ctrl or + Enter 评论
© 2023-2025 LittleRangiferTarandus, All rights reserved.
🌸 Run