一个容易忽视的CSS优先级问题

473 阅读2分钟

前言

问题开始于在网上看到了一张图,问哪个样式生效:

1.png

答案是div::first-line

诶?css优先级是怎么回事来着?查查MDN:

2.png

好家伙,不查还好,一查倒还懵逼了,怎么按理说的优先级低的反而生效了?于是网上搜博客,没有发现讲到这个问题的,大多都是重复着文档上的优先级相关内容。于是又仔细反复查看MDN,翻相关规范,有了一个猜想。

CSS优先级的前提

CSS优先级相关的知识以及权重的计算,网上博客和MDN文档说的很清楚了就不再赘述,这里只说一个理所当然而往往容易忽视掉的问题,那就是计算CSS优先级的前提:

当同一个元素有多个声明的时候,优先级才会有意义。因为每一个直接作用于元素的 CSS 规则总是会接管/覆盖(take over)该元素从祖先元素继承而来的规则。

重点就在于是同一个元素,比如下面,ID选择器虽然权重更高,但和类选择器根本就不是针对的同一个元素,所以不存在比较优先级的前提,生效的只会是类选择器。

<style>
#root { color: red; }
.a p { color: blue; }
</style>
<div id="root" class="a">
    <p>text</p>
</div>

伪元素选择器

回到开头的问题,是不是因为样式应用的不是同一个元素呢?div:first-linep#a似乎是同一个元素啊?让我们来看看规范里是怎么说的:

4.png

3.png

大概意思是伪元素是具体的元素之外的抽象元素,可以用来选择和设置文档中不一定映射到文档树结构的部分,寻找对应文本章节给的例子里,看起来像是插入了一个虚拟的<div::first-line>元素。

照着开头的例子写个demo再打开控制台查看:

5.png

6.png

发现如图上所示,样式确实没被覆盖,说明根本就不是两个样式作用于同一个元素,看来似乎这就是问题的答案了。但是MDN中又说:

一个选择器中只能使用一个伪元素。伪元素必须紧跟在语句中的简单选择器/基础选择器之后。

那似乎伪元素的优先级没啥用啊,毕竟不可能有多个伪元素选择器指向同一个伪元素,为什么会有伪元素优先级并且还最低,这个问题规范里似乎没有谈到(也有可能我没看到,太长懒得看)。

以上就算上自己对这个问题的一个猜想吧,如有不对的地方欢迎指出,互相学习。