持续创作,加速成长!这是我参与「掘金日新计划 · 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 | 标签选择器 | 1 | body { 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; } | ||
| 3 | id选择器 | 100 | #foo { color: #999; } | ||
| 4 | style 属性内联 | 1000 | 优先级 | ||
| 5 | !important | infinite | .foo[style="color: #ccc;"] { color: #fff !important; } |
3、选择器计算方法
1、归类权重比较法
根据等级、权重进行比较,从等级最高的选择器开始比较,数量多者获胜;如果高等级数量相同,则比较下一等级的选择器数量,依次类推,如果数量都相等则后者覆盖前者样式。
2、数字累加计算法
根据上表中的选择器参考计算值,数值进行累加,比较数字大小,数字大者获胜,如果数值都相等则后者覆盖前者样式。
计算示例:
| 选择器 | 参考计算值 | 等级/权重 | 计算规则 |
|---|---|---|---|
| * { } | 0 = 0 * 1 | 0 * 1 | 1个0级通配符,优先级计算值为0 |
| dialog { } | 1 = 1 * 1 | 1 * 1 | 一个标签选择器,优先级数值为1 |
| ul > li { } | 2 = 1 + 0 + 1 | 1 * 20 * 1 | 2个标签选择器,一个0级选择符 |
| .lightblue p { } | 11 = 10 + 1 | 2 * 11 * 1 | 1个类选择器,1个标签选择器 |
| div.demo2:not([dir]) {} | 21 = 1 + 10 + 0 + 10 | 2 * 21 * 10 * 1 | 1个标签,一个类选择器,一个逻辑伪类、一个属性选择器 |
| html[lang] > .demo2[class] { } | 31 = 1 + 10 + 0 + 10 + 10 | 2 * 31 * 10 * 1 | 1个标签、1个类型、2个属性、1个选择符 |
3、增加CSS选择器的优先级
.foo { color: #333; }
1、使用嵌套增加权重``
.father .foo { color: #333; }`
2、增加标签选择器
div.foo { color: #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; }