5.7 CSS选择器优先级
当多个选择器定义同一元素同一CSS属性名的不同值,会出现冲突,最终采用优先级高的选择器内的值,其它值被覆盖,这就是覆盖性,依据选择器优先级进行覆盖。CSS选择器优先级也称覆盖性。
5.7.1 生成指定值的步骤
声明值declared value生成指定值specified value的步骤示意图如下。
一个元素一个CSS属性的声明值包括4种来源:开发人员声明当前元素的属性值、浏览器为标签声明样式默认值、从祖先元素继承的属性值、属性的初始默认值。
上图4种来源值之间的虚线箭头表示:“如果当前步骤存在值,则使用当前步骤值,后续不再执行;如果当前步骤不存在值,则使用下一个步骤的值。”
(1)如果开发人员通过style属性设置该属性的值,或者通过一个选择器设置该属性值,则采用此值。style属性可理解成一种特殊的选择器,就像开发者工具标记的“element.style”选择器,后续描述选择器包括style属性这种选择器。
(2)如果开发人员在多个选择器设置该属性值,则通过选择器优先级判断采用哪个选择器的设置值。
(3)如果开发人员没有设置该属性值,则判断浏览器为该元素该属性声明的属性值,如果存在则此用此值。
(4)如果浏览器没有设置,并且该属性是可继承属性,则判断祖先元素是否存在设置,如果存在则使用此值。
(5)如果不是可继承属性,或祖先元素没有设置,则使用CSS属性初始默认值。
5.7.2 优先级判断的两个基本规则
1、自定义标签选择器与浏览器默认标签选择器的优先级
基本规则
自定义标签选择器 > 浏览器默认标签选择器
示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
<style>
body{
font-size: 14px;
line-height: 1.5;
margin: 0;
}
h1,h2,h3{
line-height: 1.2;
}
.header{
line-height: 1.4;
text-align: center;
padding: 15px 0;
}
.header h1{
font-size: 22px;
color: #0aaa76;
margin: 0;
}
</style>
</head>
<body>
<div class="header">
<h1 style="font-size: 24px;font-style: italic;">小步教程 xiaobuteach.com</h1>
</div>
</body>
</html>
查看body元素的样式。
浏览器默认设置body的margin值8px,编码设置body标签选择器margin值0。两个地方同时设置margin属性,以谁为准,就是优先级,这里以自定义选择器设置值0为准。
浏览器默认标签选择器包含属性选择器。如果按照优先级数值计算顺序,浏览器含属性选择器的标签选择器优先级更高,实际开发人员自定义的标签选择器的优先级更高。
示例代码如下。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
<style>
input{
padding-block: 20px;
}
</style>
</head>
<body>
网站名称:<input type="text" value="小步教程 xiaobuteach.com">
</body>
</html>
开发者工具样式面板查看优先级。
属性选择器的i表示忽略大小写,即type="TEXT"也能匹配。默认忽略大小写,通常不写。
如果按照优先级数值顺序,input选择器的优先级数值是(0,0,1),而input[type='text' i]的优先级数值是(0,1,1),后者大于前者,实际上前者大于后者。优先级数值后续讲解。
2、直接匹配的选择器与继承自祖先元素选择器的优先级
基本规则
直接匹配的选择器 > 继承的选择器
问题:查看header元素的应用样式,line-height属性会采用哪个选择器的设置值?
问题变成下列两项中谁的优先级更高:当前元素的类选择器,自祖先元素继承的选择器。前者大于后者。直接匹配的选择器包括开发人员自定义选择器与浏览器定义的选择器。
5.7.3 优先级判断的四大规则
优先级判断的四大规则包括:
(1)总体的优先级规则;
(2)简单选择器的优先级规则;
(3)复杂选择器的优先级规则;
(4)先后顺序规则。
5.7.4 第1大规则:总体的优先级规则
style属性 > 自定义选择器 > 浏览器默认标签选择器 > 继承选择器
自定义选择器指匹配当前元素的选择器,继承选择器指从祖先元素继承下来的选择器。
其中,自定义选择器比较复杂,在第2大规则与第3大规则继续介绍,这里先使用简单的标签选择器。
(1)开发者工具的选择器按优先级从高到低顺序显示。
开发者工具验证优先级的总体规则:查看任何一个元素的样式时,它都是按照这4项的顺序排列的,这个排列顺序表示了它们的优先级。以下是“优先级判断的两个基本规则”第1个示例h1元素的样式面板内容。
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
<style>
body{
color: #0aaa76;
}
div{
color: #4aa6fc;
}
</style>
</head>
<body>
<div style="color: #ed7d31;">小步教程xiaobuteach.com</div>
</body>
</html>
开发者工具查看样式
试一试。调试取消某个样式的属性值,查看覆盖性。
5.7.5 第2大规则:简单选择器的优先级规则
3种简单选择器包括:ID选择器、类选择器、标签选择器,它们的优先级顺序如下。
ID选择器 > 类选择器 > 标签选择器
属性选择器与伪类选择器的优先级,与类选择器的优先级相同。伪元素选择器的优先级与标签选择器的优先级相同。
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简单选择器的优先级规则</title>
<style>
div{
color: #0aaa76;
}
.class1{
color: #4aa6fc;
}
#id1{
color: #ed7d31;
}
</style>
</head>
<body>
<div id="id1" class="class1">小步教程xiaobuteach.com</div>
</body>
</html>
调试结果如下:ID选择器最高,类选择器其次,标签选择器最低。
属性选择器及伪类选择器的优先级与类选择器的优先级完全相同。示例代码。
:first-child{
color: #f00;
}
[title="title1"]{
color: #000;
}
.class1{
color: #4aa6fc;
}
当优先级判断相同,则定义在后面的选择器优先级更高。
5.7.6 第3大规则 :复杂选择器的优先级规则
鼠标悬停在选择器名称,弹出“明确性”信息,明确性是优先级的数值化表示,后续称为优先级数值。
VSCode称之“选择器特定性”。
示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
<style>
div .h1 span{color: #1af;}
div span{color: #3af;}
span{color: #5af;}
#span1{color: #7af;}
div #span1{color: #9af;}
div span#span1{color: #baf;}
#div1 .h1 span#span1{color: #daf;}
div#div1 span#span1{color: #faf;}
</style>
</head>
<body>
<div class="div1" id="div1">
<h1 class="h1" id="h1">
<span class="span1" id="span1">小步教程xiaobuteach.com</span>
</h1>
</div>
</body>
</html>
上述8个选择器都匹配到同一个元素,会以谁为准?
优先级计算步骤
第1步:计数。分别数ID选择器、类选择器、标签选择器的个数,得到:a,b,c。如果存在属性选择器与伪类选择器,它们与类选择器一起计数到第2个数值b。
以h1 .class1 h2为例:0个ID选择器;1个类选择器:.class1;2个标签选择器:h1、h2。
构成一组数值(0,1,2)。
第2步:排序。首先判断a,a大则大,无需继续判断;如果a相同,判断b,依次同理判断。如果a、b、c都相同,看它们代码的先后顺序,排在后面的优先级更高。
(0,1,2)比(1,0,0)小,直接比第1个数就确大小。
示例过程
(1)数个数结果
(2)排序结果
开发者工具已经按优先级将各选择器排序好。
5.7.7 第4大规则:选择器代码的先后顺序
当应用于同一元素的两个选择器数值相同时,根据选择器定义的先后顺序判断,后定义的选择器更高。
1、同一CSS文件的先后顺序
示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
<style>
.class1{ color:#0aaa76;}
.class2{color: #4aa6fc;}
</style>
</head>
<body>
<div class="class1 class2">小步教程xiaobuteach.com</div>
</body>
</html>
问题:优先级是以div元素class属性值的顺序(class="class1 class2")为准,还是以选择器定义的顺序(.class1{ } .class2{ } )为准?优先级只与选择器定义先后顺序有关,与class属性内先后顺序无关。
2、多个CSS文件的导入先后顺序
html文件引入多个css文件的顺序不能随意修改,它们影响优先级,当选择器优先级相同时,后导入CSS文件选择器的优先级更高。
示例html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
<link rel="stylesheet" href="test1.css">
<link rel="stylesheet" href="test2.css">
</head>
<body>
<div class="class1">小步教程</div>
</body>
</html>
test1.css
.class1{
color:#0aaa76;
/* 其它属性略 */
}
/* 其它选择器略 */
test2.css
.class1 {
color: #4aa6fc;
/* 其它属性略 */
}
/* 其它选择器略 */
此时color属性以test1.css定义的class1为准,如果html文件调整css文件的导入顺序,则以test2.css定义的为准。
<link rel="stylesheet" href="test2.css">
<link rel="stylesheet" href="test1.css">
公用性强的css文件优先级低,放在前面;个性化强的css文件优先级高,放在后面。
3、常用设计规则与技巧
当优先级数值(“明确性”)相同时,后面声明的选择器优先级更高。各大CSS框架与自定义组件经常运用这项规则:基础样式设置的选择器放在前面,突出性样式设置的选择器放在后面,保证突出性样式设置能够覆盖前者。
总之,CSS代码在文件内的位置不能随意调整,CSS文件的导入顺序不能随意调整,都可能影响指定值specified value的结果。
5.7.8 属性强制优先
!important表示属性强制优先,用于属性值之后。使用场景:既有style属性设置样式,又有其它选择器设置样式,希望违背选择器的常规规则,采用某个选择器的样式时,可通过!important声明属性强制优先。
选择器{
属性名1:属性值1 !important ;
…
}
!important; 不是针对选择器,而是针对选择器里的某个属性,可用于选择器内的多个属性。也就是说,选择器优先级低,但该属性的优先级高。
示例代码
<style>
div .h1 span{color: #1af;}
div span{color: #3af;}
span{color: #5af !important;}
#span1{color: #7af;}
div #span1{color: #9af;}
div span#span1{color: #baf;}
#div1 .h1 span#span1{color: #daf;}
div#div1 span#span1{color: #faf;}
</style>
运行结果
当一个元素的一个属性有多个选择器运用!important,则它们之间的优先级按照去除!important的优先级进行判断。
项目尽量不要使用!important,“实在没办法”才使用。因为它对设计具有相当大的破坏性,违反默认规范,不要大量使用。
5.7.9 优先级顺序规则总结
优先级顺序四大规则
(1)第一大规则:总体的优先级规则
!important > style属性 > 自定义选择器 > 浏览器默认选择器 > 继承选择器
(2)第二大规则:简单选择器的优先规则
ID选择器 > 类选择器(=属性选择器=伪类选择器) > 标签选择器(=伪元素选择器)
(3)第三大规则:复杂选择器的优先级规则
(ID选择器个数,类选择器+属性选择器+伪类选择器的个数,标签选择器+伪元素选择器的个数)排序
(4)第四大规则:优先级数值相同的先后顺序规则
后定义选择器 > 先定义选择器
后引入选择器 > 先引入选择器