任何地方都存在阶级,CSS 选择器也不例外,也会讲一个三六九等。
选择器类别
- 通配符选择器
- 标签选择器
- 类选择器
- ID选择器
- 属性选择器
- 伪类选择器
- 伪元素选择器
- 关系选择器
流传已久的阶级划分
选择器 | 权重 |
---|---|
继承父标签的样式、* 通配符选择器 | 0,0,0,0 |
标签选择器 | 0,0,0,1 |
类选择器、属性选择器、伪类选择器 | 0,0,1,0 |
ID 选择器 | 0,1,0,0 |
标签的内联样式 style 属性 | 1,0,0,0 |
样式后添加 !important | 权重无穷大 |
权重不存在进位
特别注意:权重不存在进位说法。比如 11 个类选择器叠加,那么权重就是 0,0,11,0,并不会变成 0,1,1,0。例如:
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CSS</title><style>#p {color: red;}.div1 .div2 .div3 .div4 .div5 .div6 .div7 .div8 .div9 .div10 .div11 .p {color: blue;}</style>
</head><body class="body"><div class="div1"><div class="div2"><div class="div3"><div class="div4"><div class="div5"><div class="div6"><div class="div7"><div class="div8"><div class="div9"><div class="div10"><div class="div11"><p class="p" id="p">段落文本</p></div></div></div></div></div></div></div></div></div></div></div>
</body></html>
上面代码中有 .div1 .div2 .div3 .div4 .div5 .div6 .div7 .div8 .div9 .div10 .div11 .p
这么长的类选择器,想要颠覆 id 选择器 #p
,然而官大一级压死人,没任何用处,最终还是 #p
占据上风。如:
相同权重,层级越多越大
都使用类选择器,层数越多,权重越大。如:.body .ul .li1
权重为 0,0,3,0
,.ul .li1
权重为 0,0,2,0
,.body .ul .li1
优先级就更高,毕竟人多力量大。
示例:
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CSS</title><style>.body .ul .li1 {color: blue;}.ul .li1 {color: red;}</style>
</head><body class="body"><ul id="ul" class="ul"><li id="li1" class="li1">li 文本 1</li><li id="li2" class="li2">li 文本 2</li><li id="li3" class="li3">li 文本 3</li><li id="li4" class="li4">li 文本 4</li><li id="li5" class="li5">li 文本 5</li></ul>
</body></html>
结果:
相同权重,写在后面的代码优先级高
所谓 长江后浪推前浪,前浪死在岸边上
,嗯...css 选择器的权重,就是这个道理,没有先来后到,只有后来居上。
外部样式的 link 和 内部样式的 style 都是一样的道理,谁是后浪谁最大。
此规则也适用于交叉选择相同权重的选择器,如 .body .ul #li2
和 .body #ul .li2
,权重计算结果都是 0,1,2,0
,谁在后面谁最大。
类选择器、属性选择器、伪类选择器权重相同。所以 ul li.li3
和 ul li[id="li3"]
和 ul li:nth-child(3)
优先级一样,也适用于,谁在后面谁最大。
示例:
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CSS</title><style>.ul .li1 {color: red;}.ul .li1 {color: blue;}.body .ul #li2 {color: blue;}.body #ul .li2 {color: red;}.ul li.li3 {color: blue;}.ul li[id="li3"] {color: red;}.ul li:nth-child(3) {color: green;}</style>
</head><body class="body"><ul id="ul" class="ul"><li id="li1" class="li1">li 文本 1</li><li id="li2" class="li2">li 文本 2</li><li id="li3" class="li3">li 文本 3</li><li id="li4" class="li4">li 文本 4</li><li id="li5" class="li5">li 文本 5</li></ul>
</body></html>
结果:
干不过的内联样式
内联样式(又称为 行内样式
) style 优先级比任何选择优先级都高。
示例:
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CSS</title><style>#li1 {color: red;}</style>
</head><body class="body"><ul id="ul" class="ul"><li id="li1" class="li1" style="color: blue;">li 文本 1</li><li id="li2" class="li2">li 文本 2</li><li id="li3" class="li3">li 文本 3</li><li id="li4" class="li4">li 文本 4</li><li id="li5" class="li5">li 文本 5</li></ul>
</body></html>
结果:
外挂般的 !important
功夫再高,也怕菜刀,!important
就是这菜刀外挂。css 的优先级里面,只要有了 !important
,它比任何选择器都高,包括内联样式。
!important
可以写在任何 css 属性后面,给其附加外挂,如果都有外挂,那么又到了比较权重的时候了。
示例:
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CSS</title><style>#li1 {color: red !important;}#li2 {color: red !important;}</style>
</head><body class="body"><ul id="ul" class="ul"><li id="li1" class="li1" style="color: blue;">li 文本 1</li><li id="li2" class="li2" style="color: blue !important;">li 文本 2</li><li id="li3" class="li3">li 文本 3</li><li id="li4" class="li4">li 文本 4</li><li id="li5" class="li5">li 文本 5</li></ul>
</body></html>
结果:
神奇的伪元素选择器
伪元素选择器如流氓一般,跳出三界外,不在五行中,!important
也拿它没办法。
示例:
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CSS</title><style>/* 匹配第一个文字 */::first-letter {color: #990099;}/* 匹配第一行文本 */::first-line {color: green;}</style>
</head><body class="body"><ul id="ul" class="ul"><li id="li1" class="li1" style="color: red !important;">标签 li 文本 1 <br> 第二行</li><li id="li2" class="li2">标签 li 文本 2</li><li id="li3" class="li3">标签 li 文本 3</li><li id="li4" class="li4">标签 li 文本 4</li><li id="li5" class="li5">标签 li 文本 5</li></ul>
</body></html>
::first-line
命中第一行文本,::first-letter
命中第一个字符,style="color: red !important;"
强制设为红色。
然而就算是内联样式,并且有 !important
存在,也没打赢 ::first-line
。
然而就算 ::first-line
写在后面,也输给了前面的 ::first-letter
。
结果:
可以理解为伪元素选择器直接作用于独立的渲染实体(比如第一行文本、第一个字符),而其他选择器命中的规则是设置在元素之上,内部文本其实是继承了元素的样式,由于继承的样式权重最低,所以就算元素上带有 !important
规则,也无法覆盖伪元素选择器的样式。
关系选择器如小透明一般
如 .ul > .li1
比 .ul .li1
好像多了一层,然而两者权重相同,写在后面的优先级高。
示例:
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CSS</title><style>.ul > .li1 {color: red;}.ul .li1 {color: blue;}</style>
</head><body class="body"><ul id="ul" class="ul"><li id="li1" class="li1">标签 li 文本 1</li><li id="li2" class="li2">标签 li 文本 2</li><li id="li3" class="li3">标签 li 文本 3</li><li id="li4" class="li4">标签 li 文本 4</li><li id="li5" class="li5">标签 li 文本 5</li></ul>
</body></html>
结果:
总结
!important > 行内样式 > ID选择器 > 类选择器/属性选择器/伪类选择器 > 标签选择器/伪元素选择器 > 通配符选择器。关系选择器本身不单独存在,它们的优先级取决于其中的各个选择器的组合。