CSS选择器的优先级 | 青训营笔记

130 阅读3分钟

这是我参与「第四届青训营」笔记创作活动的第1天。

一个没有计算机基础的同学入门前端, 也可以在第一天写出一个样式不错的静态网页。但是,大部分人,包括我,其实并不清楚浏览器是如何通过CSS确定最终的网页样式的。在上了《深入CSS》这届课之后,我的很多问题都得到了解答。

当多个选择器匹配到同一个元素时,如何确定元素的样式? 下面我对CSS选择器的优先级规则做一个总结。

选择器的特异度(Specificity)

每一个选择器都有相应的权重,权重为一个三维向量,初始值 0-0-0。一个选择器根据如下规则决定最终权重:

  1. 每出现一个 id选择器, 权重增加 1-0-0
  2. 每出现一个 class选择器,attribute选择器,pseudo-class选择器,权重增加 0-1-0
  3. 每出现一个 type选择器,pseudo-element选择器,权重增加 0-0-1
  4. 通配选择符 * , 关系选择符 >, +, ~等,伪类 :is(), :not():where()不增加权重

考虑如下的HTML代码片段

<div class="container" id="box1">
    <div class="card" id="box2">
        <h1 id="title">Hello world</h1>
        <a href="https://juejin.cn/">前往掘金</a>
    </div>
</div>

根据上述规则,我们可以计算各个选择器的权重

  • #box2 .title 的权重为 1-1-0
  • a:hover 的权重为 0-1-1
  • .card::before 的权重为 0-1-1

权重高低的比较方法为依次比较权重的各个分量,比如 1-0-0 高于 0-5-8, 2-3-0 高于 2-2-4。当多个选择器定义的样式产生冲突时, 选择权重最高的选择器。

若多个权重相同的选择器匹配到了同一个元素,则遵循"后来者优先"规则,选取CSS文件中最后出现的选择器对应的样式。

特殊规则

1. :is(), :not(), :where()伪类选择器

  • 虽然以上三个伪类选择器本身不会增加权重, 但是其内部声明的选择器会影响其权重
  • :where()里出现的选择器也不会增加权重
  • :is(), :not()内部声明的各组选择器中,选择权重最高的一组作为其权重

我们还是通过几个例子加深印象

  • :where(#container) h1 的权重为 0-0-1
  • :is(#box1, .card) h1 的权重为1-0-1

2. 内联样式

在HTML文件中直接定义的style会覆盖CSS文件中的style. 例如

<h1 id="title" style="color:blue;">Hello world</h1>
#title {
    color: red;
}

在开发者工具查看样式

image.png

3. !important

如果想要在CSS中覆盖内联样式,就需要在样式里加上 !important字样,比如

image.png

注: 在HTML文件直接定义样式,以及用!important关键字都不是一个好的实践,应该尽量避免.

总结

  1. 样式中有!important,则优先考虑带有!important的样式, 若有多个带有!important的样式,则这些样式之间继续按照下列规则比较优先级
  2. 在HTML文件中直接定义的内联样式优先级高于CSS文件中定义的样式
  3. 在CSS文件中,采用权重最高的选择器定义的样式
  4. 若多个选择器都是最高权重,则选择这些选择器中最后出现的选择器的样式

参考资料

MDN:Specificity developer.mozilla.org/en-US/docs/…