CSS 权重计算

423 阅读3分钟

印象中 CSS 选择器的权重计算规则很简单,没有特别的地方,今天有空看了几篇博客,发现跟我认为的竟然有不一样的,所以记录整理一下。

结论

先说结论:

image.png
PS: 图片英文拼写错了,应该是 pseudo-classes

权重计算包括四位:a, b, c, d。官方文档

  • a 位置是否有 style=" " 内联写法,有的话权重计算结果是 1,0,0,0
  • b 位置表示计算选择器中 ID 属性的数量,有一个 ID 选择器那么权重计算结果是 0,1,0,0
  • c 位表示 class 选择器、属性选择器、伪类选择器的数量,例如一个 class 选择器权重计算结果是 0,0,1,0
  • 元素选择器(包括伪元素选择器如 :first-line)权重计算结果是 0,0,0,1

比较的顺序先比较 a 位置上数字,a 位置数字较大的样式生效;如果 a 位上的数字相同,则比较 b 位置上的数字,b 位置数字较大的样式生效;如果 b 位上的数字相同,则比较 c 位置上的数字,依次比较。

通配选择符(universal selector)(*关系选择符(combinators)(+>~' '||)和 否定伪类(negation pseudo-class)(:not())对优先级没有影响(但是,在 ****:not() 内部声明的选择器会影响优先级)。

上例子:

  <style>
    .favorite {
      color: red;
      font-weight: bold;
    }
    li#fa-one{
      color: yellow
    }
    #summer-drinks li{
      color: blue;
    }
  </style>
  <ul id="summer-drinks">
    <li class="favorite" id="fa-one" style="color: green;">Whiskey and Ginger Ale</li>
    <li>Wheat Beer</li>
    <li>Mint Julip</li>
 </ul>

style=" "内联写法的权重是 1,0,0,0
#summer-drinks li 写法的权重是 0,1,0,1
li#fa-one 写法的权重是 0,1,0,1
.favorite 写法的权重是 0,0,1,0

style a 位置数字是 1, 其他写法都是 0 ,所以style=" "内联样式生效。

image.png

#summer-drinks lili#fa-one 计算结果是一样的,这点要注意了,当我们把style=" "内联去掉后,会根据#summer-drinks lili#fa-one 的位置,选择更靠后的,为什么?因为权重计算结果是相同的,则更靠后的会覆盖前面的写法。

再来一个例子:

  <style>
    a[title]{
      color: red
    }
    a:hover{
      color: green;
    }
    .testA{
      color: purple;
    }
  </style>
 <ul>
   <li><a title="w3c" class="testA">W3C</a></li>
   <li><a>Medium</a></li>
 </ul>

根据计算规则:
a[title] 的是 attributes 选择器 + 元素选择器组成,故权重计算值为:0,0,1,1 .testA 只是 class 选择器,权重计算值为: 0,0,1,0
所以 W3VC 标签显示为红色

image.png
a:hover 的是伪类选择器 + 元素选择器,权重计算值也是:0,0,1,1 ,跟 a[title] 计算结果是一样的,但是,a:hover 的定义更靠后,所以 a:hover 的样式在 hover 的时候生效。

image.png
更多例子:

image.png

❌ 1000、100、10、1 误区

不要把 style=" " 内联写法 1,0,0,0 当做 1000 ;ID 选择器 0,1,0,0 当做 100 去计算比较,正确的比较方法看上面。是按照位次,每个位置上数字分别比较的。

一个例子:

样式一:body header div nav ul li div p a span em {color: red}

样式二:.count {color: blue}

按照错误的计算方法,样式一的权重值是11,样式二的权重值是10,如果这两条规则用于同一个元素,则该元素应该是红色。实际结果却是蓝色。

正确的计算结果是:0,0,0,11 和 0,0,1,0。从第一位 a 开始比较,a 和 b 位上都是0;比较 c 位,样式二的是 1 大于样式一,所以样式二生效。

关于 !important

!important 的优先级最高,不参与上面权重计算。如果两个选择器同时使用了!important,那么会根据上面的计算权重的规则进行权重计算,从而决定到底是哪一种样式生效。

最好不要使用 !important,尤其在我们写第三方组件库的时候。

如果想要覆盖 !important 的样式,可以给样式加上 !important 并且权重计算结果比之前的大即可;或者跟之前的相同但是要声明在后面,这样可以覆盖之前的 !important 样式。

css-tricks.com/specifics-o…
juejin.cn/post/684490… chenhaizhou.github.io/2015/01/16/…