CSS系列-选择器优先级计算技巧

133 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天

选择器的优先级

1、举几个常见的例子,带着问题看优先级和选择器的计算,以下颜色分别是???

demo1

<div class="demo1">
  <div class="lightblue">
    <div class="darkblue">
      <p>1、颜色?</p>
    </div>
  </div>
  <div class="lightblue">
    <div class="darkblue">
      <p>2、颜色?</p>
    </div>
  </div>
</div>
 
<style>
  .lightblue p { color: lightblue }
  .darkblue p { color: darkblue }
</style>

demo2

<html lang="en">
  <body>
    <div class="demo2">demo2的颜色</div>
  </body>
</html>
 
 
body .demo2 { color: red }
html .demo2 { color: blue }

demo3

<html lang="en">
  <body>
    <div class="demo3">demo3的颜色</div>
  </body>
</html>
 
div.demo3:not([dir]) { color: red }
html[lang] > .demo3[class] { color: blue }

demo4

<html lang="en">
  <header>
    <style>
      @import "test1.css";
      .demo4 { color: yellow; }
    </style>
    <link type="text/css" rel="stylesheet" href="test2.css">
  </header>
   
  <body>
    <div class="demo4">demo4的颜色</div>
  </body>
</html>
 
 
==test1.css
.demo4 { color: red; }
 
 
==test2.css
.demo4 { color: blue; }

2、选择器优先级分类

CSS的优先级有着明显 “不可逾越” 的等级制度,一般将其划分6个等级(0~5),前四个等级有css选择器决定,后面两个等级有书写方式和特定语法决定。下面对6个等级进行分类。

等级/权重选择器参考计算值示例
等级/权重选择器参考计算值示例
0通配选择器、选择符、逻辑组合伪类0通配符:* { color: #000; }选择符:+、>、~、、 空格 等逻辑组合伪类: :not()、:is()、:where,这些伪类本身不影响CSS优先级,影响优先级的是括号里面的选择器
1标签选择器1body { color: #333; }
2类选择器、属性选择器、伪类伪类:用户行为伪类(hover/active/focus 等等)url定位伪类(link/visited/any-link/target等等)输入状态伪类(enabled/disabled等)树结构伪类(root/empty/first-child) 等等10.foo { color: #666; }[foo] { color: #666; }:hover { color: #333; }
3id选择器100#foo { color: #999; }
4style 属性内联1000优先级
5!importantinfinite.foo[style="color: #ccc;"] { color: #fff !important; }

3、选择器计算方法

1、归类权重比较法

根据等级、权重进行比较,从等级最高的选择器开始比较,数量多者获胜;如果高等级数量相同,则比较下一等级的选择器数量,依次类推,如果数量都相等则后者覆盖前者样式。

2、数字累加计算法

根据上表中的选择器参考计算值,数值进行累加,比较数字大小,数字大者获胜,如果数值都相等则后者覆盖前者样式。

计算示例:

选择器参考计算值等级/权重计算规则
* { }0 = 0 * 10 * 11个0级通配符,优先级计算值为0
dialog { }1 = 1 * 11 * 1一个标签选择器,优先级数值为1
ul > li { }2 = 1 + 0 + 11 * 20 * 12个标签选择器,一个0级选择符
.lightblue p { }11 = 10 + 12 * 11 * 11个类选择器,1个标签选择器
div.demo2:not([dir]) {}21 = 1 + 10 + 0 + 102 * 21 * 10 * 11个标签,一个类选择器,一个逻辑伪类、一个属性选择器
html[lang] > .demo2[class] { }31 = 1 + 10 + 0 + 10 + 102 * 31 * 10 * 11个标签、1个类型、2个属性、1个选择符

3、增加CSS选择器的优先级

.foocolor#333; }
1、使用嵌套增加权重``
.father .foocolor#333; }`
2、增加标签选择器
div.foocolor#333; }

如何避免在父元素类名变化或者标签变化对样式造成的影响???

相信别人,不如相信自己


.foo { color: #333; }
 
 
1、重复自身选择器
.foo.foo { color: #333; }
 
 
2、借助自身属性选择器
.foo[class] { color: #333; }
#foo[id] { color: #333; }

4、总结

1、

  • 等级压制
  • 数量取胜
  • 后来居上,1、选择器与dom顺序无关;2、与html文档中位置有关,与加载顺序无关。
  • 书写习惯远比知识更重要。

2、冷知识

  • 数值计算法存在的问题:1 ~ 10 的差距站在极限的角度来讲有点小,这就意味着10个标签选择器的优先级就可以和1个类名选择器平起平坐了。然而事实并非如此,就像开篇所说,选择器存在 “不可逾越” 的等级制度。由于实际的开发中,我们是不会写多达10个以上的选择器的,所以使用数据计算法一般不会影响计算结果。

  • 256个选择器越级现象

    • ie 存在越级现象, chrome/firefox 等浏览器不存在。原因:类名以8字节字符串存储,8字节能容纳的最大值就是255,所以256个类名会越过边缘溢出到ID区域,后来采用16字节的字符串进行存储。所以不会出现越级现象。
<span class="foo" id="foo">颜色</span>
 
 
#foo { color: red; }
 
 
.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo
{ color: blue; }