CSS入门8-三大特性之层叠特性与优先级
(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!)
(注2:更多内容请查看我的目录。)
1. 简介
所谓的层叠性与优先级,其实说白了可以理解为,不同的规则起冲突的情况下,听谁的呢?有的时候这种冲突很容易解决,有的时候我们自己都难以决断,比如好声音三位导师都选你,该跟谁走呢。索性css给出了这些规则的优先级,不需要我们去苦恼。
2. 样式作用情况
元素的样式该如何去展现呢,首先看一下某个元素某个属性可能作用样式的情况:
- 没有指定样式(没有内联样式也没有选择器选中指定样式)
- 有唯一指定样式(有内联样式或者选择器选中,且只有一个规则作用于该属性)
- 有多个样式规则 (有内联样式或者选择器选中,且不只一个规则作用于该属性)
下面我们来详细分析一下这三种情况。
3. 优先级分析
3.1 有唯一指定样式的情况
我们先来看有唯一指定样式的情况,因为,这种情况最简单,就一个选择,也别挑了,说啥就是啥。我们还是来大致看看。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.1</title>
<style>
p {
color: blue;
}
.green {
color: green;
}
</style>
</head>
<body>
<div>
<div style="color: red">内联唯一指定</div>
<p>元素唯一指定</p>
<div class="green">类唯一指定</div>
</div>
</body>
</html>
结论:若只有唯一指定样式,以该样式为准。
3.2 多个样式规则
多个样式规则冲突,其实有很多种情况。还记得我们学过样式引入方式有四种,涉及三种样式,分别是内联,内部和外部(参考CSS入门4-引入CSS)。首先我们来看只引入其中一种类型的情况下,出现冲突该如何解决。
3.2.1 仅有一种样式类型的情况(内联,内部或者外部)
3.2.1.1 仅有内联
仅有内联的情况下,要出现冲突,只可能是在style中多次对同一个属性赋值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.1</title>
</head>
<body>
<div style="color: red;color: blue;">
仅有内联,谁在后面,谁优先
</div>
</body>
</html>
3.2.1.1
看上图,审查一下元素,可以看到该元素样式中,前面的red被覆盖了,color最后的取值是blue。最右边文字的颜色确实也是蓝色。
结论:只有内联样式,后面的属性赋值优先级大于前面的属性赋值。
3.2.1.2 仅有内部样式
内部样式,已经可以选择多种选择器来指定样式。所以,这里情况比内联会复杂很多。首先来复习一下选择器的种类,可以参考CSS入门5-选择器。这么多的选择器类型和组合关系,可能都会产生冲突,这个时候怎么办呢,想想都复杂,我们继续拆分问题。将选择器分为四类:
- 常用选择器,包括元素选择器,类选择器,id选择器和属性选择我器
- 伪类选择器和伪元素选择器
- 关系选择器
- 通配选择器
3.2.1.2.1 常用选择器
3.2.1.2.1.1 同一类选择器(包括同一个选择器)先后冲突
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.1.1</title>
<style>
.text-color-black {
color: black;
}
.text-color-red {
color: red;
}
p {
color: blue;
}
p {
color: green;
}
</style>
</head>
<body>
<div class="text-color-black text-color-red">red</div>
<div class="text-color-red text-color-black">red</div>
<p>green</p>
</body>
</html>
3.2.1.2.1.1
可以看到div中两个类对颜色的定义冲突时,不管class定义的顺序如何,以style中类的顺序为准,后面的覆盖前面的样式。如果是同一选择器,也是后者覆盖前者,这种情况可以涵盖在同类选择器的情况下。
结论:同类型选择器(类型一样,即同为元素选择器,类选择器,id选择器或者属性选择器),按style中的先后顺序,后者优先级更高。
3.2.1.2.1.2 不同类选择器相互冲突
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.1.2</title>
<style>
#test {
color: orange;
}
.text-color-red {
color: red;
}
[otitle='test'] {
color: purple;
}
div {
color: grey;
}
[otitle='testReverse'] {
color: purple;
}
.text-color-red-reverse {
color: red;
}
#testReverse {
color: orange;
}
</style>
</head>
<body>
<div class="text-color-red" id="test" otitle="test">从上到下,id,类,属性和元素pk,id赢</div>
<div class="text-color-red-reverse" id="testReverse" otitle="testReverse">从下到上,id,类,属性和元素pk,id赢</div>
<div otitle="test" class="text-color-red">从上到下,类,属性和元素pk,属性赢</div>
<div otitle="testReverse" class="text-color-red-reverse">从下到上,类,属性和元素pk,类赢</div>
<div class="text-color-red">从上到下类和元素pk,类赢</div>
<div class="text-color-red-reverse">从下到上类和元素pk,类赢</div>
<div otitle="test">从上到下属性和元素pk,属性赢</div>
<div otitle="testReverse">从下到上属性和元素pk,属性赢</div>
</body>
</html>
test3.2.1.2.1.2
我们选择正反两种顺序,来看不同选择器之间的比较。首先,四种选择器在一起时,id选择器获胜。然后排除id选择器,剩余三种选择器比较时,类和属性谁在下边谁赢,也就是后者覆盖前者。最后,元素分别与类和属性比较,发现元素都输了。
结论:id > (类和属性) > 元素,类和属性同级,遵循同级元素后者覆盖前者的规则。
注:查看某个元素样式的时候,调试窗口是按照优先级规则从小到大往上排的,越往上的规则优先级越高,对同个属性的样式规定将会覆盖下面低优先级的样式规定。
3.2.1.2.2 伪类选择器和伪元素选择器
3.2.1.2.2.1 伪类选择器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.1.2-1</title>
<style>
#test {
color: red;
}
#targetone {
color: red;
}
.test {
color: orange;
}
[otitle] {
color: purple;
}
a {
color: blue;
}
input {
color: blue;
}
:link {
color: green;
}
:hover {
color: black;
}
:target {
color: yellow;
background: darkblue;
}
:disabled {
color: grey;
}
:first-child {
color: aqua;
}
:last-child {
color: aqua;
}
</style>
</head>
<body>
<div>
<a href="#targetone" id="test" class="test" otitle>123</a>
<br>
<input class="test" value="targettwo">
<br>
<input id="targetone" class="test" disabled="disabled" value="targetone">
</div>
</body>
</html>
注:要想在调试器看到动态伪类效果,需要在styles中勾选该效果。
3.2.1.2.2.1-1.1
3.2.1.2.2.1-1.2锚点未点击
3.2.1.2.2.1-1.3锚点已点击
看上面示例,我们在style内先按id,类,属性,元素,静态伪类(只应用于超链接),动态伪类(可应用于任何元素),目标伪类:target(IE8-不支持,匹配锚点对应的目标元素),UI元素伪类(IE8-不支持),结构伪类(IE8-不支持)的顺序指定规则。结果发现其表现如下:
a:id > 结构伪类 > 动态伪类 > 静态伪类 > 属性 > 类 > 元素 > 浏览器默认属性 > 继承属性
input:id > 结构伪类 > UI元素伪类 > 目标伪类 > 动态伪类 > 类 > 元素 > 浏览器默认属性 > 继承属性
我们合并一下这两个结论,有如下结论:
3.2.1.2.2.1-1 id > 结构伪类 > UI元素伪类 > 目标伪类 > 动态伪类 > 静态伪类 > 属性 > 类 > 元素 > 浏览器默认属性 > 继承属性
(当然,需要注意的是,并不是每个元素都有这些属性的)
然后,我们将style内各规则倒序一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.1.2-2</title>
<style>
:last-child {
color: aqua;
}
:first-child {
color: aqua;
}
:disabled {
color: grey;
}
:target {
color: yellow;
background: darkblue;
}
:hover {
color: black;
}
:link {
color: green;
}
input {
color: blue;
}
a {
color: blue;
}
[otitle] {
color: purple;
}
.test {
color: orange;
}
#targetone {
color: red;
}
#test {
color: red;
}
</style>
</head>
<body>
<div>
<a href="#targetone" id="test" class="test" otitle>123</a>
<br>
<input class="test" value="targettwo">
<br>
<input id="targetone" class="test" disabled="disabled" value="targetone">
</div>
</body>
</html>
3.2.1.2.2.1-2.1
3.2.1.2.2.1-2.2锚点未点击
3.2.1.2.2.1-2.3锚点已点击
结果发现其表现如下:
a:id > 类 > 属性 > 静态伪类 > 动态伪类 > 结构伪类 > 元素 > 浏览器默认属性 > 继承属性
input:id > 类 > 动态伪类 > 目标伪类 > UI元素伪类 > 结构伪类 > 元素 > 浏览器默认属性 > 继承属性
我们合并一下这两个结论,有如下结论:
3.2.1.2.2.1-2 id > 类 > 属性 > 静态伪类 > 动态伪类 > 目标伪类 > UI元素伪类 > 结构伪类 > 元素 > 浏览器默认属性 > 继承属性
综合3.2.1.2.2.1-1和3.2.1.2.2.1-2来看,我们再次验证了类和属性同级,并且发现它们和伪类也是同级的。有如下结论:
结论:id > (类,属性,伪类) > 元素,类,属性和伪类同级,遵循同级元素后者覆盖前者的规则。
3.2.1.2.2.2 伪元素选择器
伪元素,说是元素,但又不是真实的元素,是一个虚拟的元素。如何详细理解这段话呢,我们来看一下下面这个例子。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.2.2</title>
<style>
:first-child {
color: red;
}
:last-child {
color: red;
}
p:before {
content: 'abc';
color: blue;
}
p:after {
content: 'def';
color: purple;
}
:hover {
color: black;
}
</style>
</head>
<body>
<div>
<p>123</p>
<p>456</p>
</div>
</body>
</html>
3.2.1.2.2.2-1
3.2.1.2.2.2-2
从上面两幅图可以看出,伪元素其实是在元素内容内虚拟创建了一个元素,且无法被其他选择器选取。所以对于伪元素的样式,不用考虑优先级
3.2.1.2.3 关系选择器
3.2.1.2.3.1 社群关系-分组选择器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.3.1</title>
<style>
.test01 {
color: red;
}
.test02 {
color: black;
}
.test01, .test02 {
color: blue;
}
.test03, .test04 {
color: blue;
}
.test03 {
color: red;
}
.test04 {
color: black;
}
</style>
</head>
<body>
<div>
<div class="test01 test02">123</div>
<div class="test03 test04">123</div>
</div>
</body>
</html>
3.2.1.2.3.1-1
3.2.1.2.3.1-2
以上两图可以看到,社群关系不会影响其本身的权重,即同时指定多个选择器和单独指定这些选择器效果一样。
3.2.1.2.3.2 亲戚关系
3.2.1.2.3.2.1 不同关系类型的比较
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.3.2.1-1</title>
<style>
div p {
color: red;
}
div > p {
color: orange;
}
p ~ p {
color: blue;
}
p + p {
color: green;
}
</style>
</head>
<body>
<div>
<p>123</p>
<p>456</p>
</div>
</body>
</html>
3.2.1.2.3.2.1-1
先按后代,子代,通用兄弟,相邻兄弟在style中排序,发现后面的优先级高。然后顺序反过来:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.3.2.1-2</title>
<style>
p + p {
color: green;
}
p ~ p {
color: blue;
}
div > p {
color: orange;
}
div p {
color: red;
}
</style>
</head>
<body>
<div>
<p>123</p>
<p>456</p>
</div>
</body>
</html>
3.2.1.2.3.2.1-2
发现仍然是后者覆盖前者,也就是说关系型选择器的不同关系之间没有优先级。
3.2.1.2.3.2.2 相同关系内部成员数量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.3.2.2</title>
<style>
div {
color: yellow;
}
div div {
color: red;
}
div div div {
color: orange;
}
section section section {
color: orange;
}
section section {
color: red;
}
section {
color: yellow;
}
</style>
</head>
<body>
<div>
<div>
<div>123</div>
</div>
</div>
<section>
<section>
<section>456</section>
</section>
</section>
</body>
</html>
3.2.1.2.3.2.2
上图说明,亲戚关系中,成员数量越多,优先级越高。
3.2.1.2.3.2.3 相同关系内部成员成份顺序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.3.2.3</title>
<style>
div .test02 {
color: yellow;
}
.test01 div {
color: orange;
}
div .test03 {
color: red;
}
</style>
</head>
<body>
<div class="test01">
<div class="test02">123</div>
<div class="test03">456</div>
</div>
</body>
</html>
3.2.1.2.3.2.3
上图说明,交换不同类型成员的顺序并不影响优先级。
3.2.1.2.3.2.4 相同关系内部成员成份组成
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.3.2.4</title>
<style>
#test01 #test02 {
color: red;
}
#test01 .test02 {
color: orange;
}
#test01 div {
color: black;
}
.test01 .test02 {
color: grey;
}
.test01 div {
color: yellow;
}
div div {
color: blue;
}
.test03 div {
color: yellow;
}
.test03 .test04 {
color: grey;
}
#test03 div {
color: black;
}
#test03 .test04 {
color: orange;
}
#test03 #test04 {
color: red;
}
</style>
</head>
<body>
<div class="test01" id="test01">
<div class="test02" id="test02">123</div>
</div>
<div class="test03" id="test03">
<div class="test04" id="test04">123</div>
</div>
</body>
</html>
3.2.1.2.3.2.4-1
3.2.1.2.3.2.4-2
由上面图片可以看出,在亲戚关系内部,成员的重要性和其单独出现时的重要性保持一致,即id>类>元素。
由以上几点结论可以得出,亲戚关系发生冲突时,先看id选择器数量,谁多谁大,一样多就看类(及其同级)选择器,谁多谁大,若还是一样多,则看元素选择器,谁多谁大。如果仍然一样多,谁在后面谁优先。
3.2.1.2.4 通配选择器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.4</title>
<style>
input {
color: red;
}
* {
color: blue;
}
</style>
</head>
<body>
<input type="text" value="123" disabled="disabled">
</body>
</html>
3.2.1.2.4
可以看出,通配选择器样式优先级仅比浏览器默认样式和继承样式优先级高一些。
总结3.2.1.2 仅有内部样式的情况,有如下结论:
- (级别)对于不同元素,有如下优先级别,id > 类(属性,伪类)> 元素 > 通配符 > 浏览器默认样式 > 继承样式
- (个数)样式冲突时,比较两者的最高级别选择器的级别,级别高的胜出。若级别一样,则比较其个数,个数多的胜出。若一样,则比较次一级别的级别与个数,如此循环往下,直到有一个胜出或者打平。
- (顺序)若两者级别及其个数一样,则后者覆盖前者。
ps:对于社群关系,在比较优先级时,将其理解为在该位置拆按顺序成一个个单独的个体即可。
3.2.1.3 仅有外部
3.2.1.3.1 外部样式在一个文件内部发生冲突
这种情况的表现形式与内部样式一样。
3.2.1.3.2 外部样式在多个文件之间发生冲突
这种情况遵循后者覆盖前者的原则,后面的link优先于前面的link,而不管其加载的顺序如何。
3.2.2 多种样式类型的情况(内联,内部和外部相互作用)
内联 > 内部 > 外部
4.总结
- !important最优先(特权阶级)
- 比较样式文件类型,内联 > 内部 > 外部 (内外有别)
- 比较样式权重,按级别,个数与顺序进行计算 (亲疏有别,量大优先,后来居上)