引言
许多小伙伴即将面临找工作,正在为面试忙碌准备,但在日常开发中,常因依赖框架而逐渐忽略了一些基础知识,比如------CSS 选择器以及其优先级权重,你还记得吗? 如果你也遇到过样式冲突而找不到原因,或者面试时被问到选择器优先级的计算而手忙脚乱,那么这篇文章正是为你而写!
接下来,我们将从基础规则讲起,带你逐步了解CSS选择器的概念、掌握 CSS 选择器的优先级权重计算,轻松应对日常开发和技术面试!
本篇文章将主要讲述CSS选择器的优先级权重计算 。由于篇幅限制,如果是想看关于CSS选择器 内容的小伙伴,请移步我的另外一篇文章: CSS 选择器和优先级权重计算这么简单,你还没掌握?一篇文章让你轻松通关面试!(上)
正文
CSS选择器的优先级权重计算
什么是权重问题?
权重问题 ,也被称为样式层叠问题,是指当同一个元素上应用了多次相同的样式时,发生冲突时应该以哪个样式为准。也就是"谁说了算"的问题。
在深入了解权重问题之前,我们先回顾一下样式表之间的优先级:
在CSS中,样式表有以下三种常见的定义方式:
-
行内样式
通过直接使用
style
属性定义样式,例如<spanstyle="xxx">
。- 优点:不需要依赖选择器,样式直接作用在当前元素上。
- 缺点:没有实现样式与结构的分离,维护和修改都很麻烦,因此不推荐使用。
-
内部样式
在HTML文件中,通过
<style>
标签写样式,例如:html<style> p { color: red; } </style>
- 优点:相对集中,适用于小型项目或临时调试。
- 缺点:当样式较多时,文件会变得难以管理。
-
外部样式
将样式定义在单独的CSS文件中,然后通过
<link>
标签引用,例如:<link rel="stylesheet" href="styles.css">
- 优点:实现样式与结构的完全分离,便于管理和复用。
- 缺点:需要额外的文件。
当上述三种样式表中的同一属性同时作用于同一元素时,必然会发生冲突。那么这时的优先级规则为:行内样式 > 内部样式 = 外部样式。
拓展:
看完这三种样式表的优先级后,你会不会觉得行内样式应该就是优先级最高的了?其实还有优先级比它更高的规则,只不过人家不是选择器,也不是样式表,而是放在属性值后面的一个写法 ------它就是important。
写法 :在你希望强调的属性后加上
!important
。
css.test { color: red !important; }
注意 :通过这种方式,你可以确保该属性无论在哪里都会优先应用。但是由于
!important
具有极高的优先级,所以过度依赖它就会导致代码变得难以维护。
那么如果在同一类型的样式表 中,通过不同选择器选中了同一个元素,再出现冲突应该听谁的?这就是我们今天要研究的权重问题。
基本选择器权重
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<h2>超级无敌霹雳螺旋丸!</h2>
</body>
</html>
css
h1 {
color: blue;
font-size: 12px;
}
* {
color: aqua;
}
在这段代码中,h1{}
和 *{}
的样式显然发生了冲突。然而,最终生效的样式却是 h1{}
的样式。为什么会这样呢?
我们可以调换样式的位置,再次运行,发现无论顺序如何变化,h1{}
的样式始终优先应用。这表明,标签选择器 和 通配符选择器 之间是有优先级关系的,也就是说它们的权重不同:
标签选择器 > 通配符选择器
进一步验证其他的基本选择器,我们可以就得出基本选择器的优先级顺序:
id 选择器 > 类选择器 > 标签选择器 > 通配符选择器
复合选择器权重
规则讲解
复合选择器的权重通常通过abc 方法来计算。这种方法就是分别计算出你想要比较的选择器在a、b、c三个位置上的权重值,然后按顺序 进行比较。只要某一位置的权重不同,就停止比较,谁的值更大,谁的权重就更高,最终得出谁的优先级更高。
(如果三个值都一样,那么采用后来者居上的原则:顺序在后面的优先级更高)
具体计算方式如下:
- a :计算选择器中id选择器的个数。
- b :计算选择器中类选择器 、伪类选择器 和属性选择器的个数。
- b :计算选择器中元素选择器 和伪元素选择器的个数。
有些小伙伴可能会问:这不是在讲复合选择器的权重计算吗?怎么abc的位置里除了伪类选择器 和伪元素选择器,其他的都是基本选择器?
其实,这是因为复合选择器本质上是由多个基本选择器组合 而成的。除了伪类选择器和伪元素选择器外,复合选择器的权重来自于这些基本选择器的组合。正是这种组合使得复合选择器的权重比单一选择器要高。因此,在计算复合选择器的权重时,我们可以将其拆解成多个基本选择器,然后按照上述规则进行计算。
Tips
当你一眼看过去,看到各种选择器,可能会觉得有些混乱,不知道该从哪里开始。其实,计算选择器权重时,我们并不需要那么复杂,可以通过以下几个简单的规则来帮助你快速判断:
-
a :由于id选择器 的唯一特征是
#
,因此只需要计算选择器中#
的个数即可。 -
b :同理,类选择器 、伪类选择器 和 属性选择器 都有明显的标志:
.
(类选择器)、:
(伪类选择器)和[]
(属性选择器)。只需要计算这些符号的个数即可。不过,要记住,伪元素选择器 的标志是::
(双冒号),需要和单冒号区分开来哦。 -
c :最后,元素选择器 和 伪元素选择器 也很简单。只需计算元素名称(例如
div
、span
、h1
等)和::
(伪元素选择器)的个数。
案例分析
光靠说规则,大家可能还不能够具体地认识到如何计算权重,下面我们来通过具体的例子解释一下:
css
.container span.name {
color: blue;
}
div p span:nth-child(1) {
color: orange;
}
在这个例子中,第一个选择器是 .container span.name
,第二个选择器是 div p span:nth-child(1)
。要比较它们的权重,就使用abc的方法,先依次计算两个选择器的abc的值,再按照顺序比较。
计算:
-
计算a的值:找id选择器的个数。由于两个选择器都没有使用id选择器,所以a的值都为0。
-
计算b的值:找类选择器、伪类选择器和属性选择器的个数。
- 第一个选择器
.container span.name
包含两个类选择器(.container
和.name
),因此b位置的权重为2。 - 第二个选择器
div p span:nth-child(1)
只有一个伪类选择器nth-child(1)
,所以b位置的权重为1。
- 第一个选择器
其实进行到这一步,答案已经能够出来了:第一个选择器的优先级更高,不需要再进行下一步计算。但为了熟悉计算权重的方法,我们把c的值一并算出来。
-
计算c的值:找元素选择器和伪元素选择器的个数。
- 第一个选择器
.container span.name
包含两个元素选择器(span
和span
),所以c位置的权重为2。 - 第二个选择器
div p span:nth-child(1)
包含三个元素选择器(div
、p
和span
),所以c位置的权重为3。
- 第一个选择器
比较:
- 比较a的值:两个选择器的a的值都为0,权重相同。
- 比较b的值:第一个选择器的b的值为2,第二个选择器的b的值为1,b的值已经出现不同,比较停止。第一个选择器的权重大。
结论:
.container span.name
的权重比 div p span:nth-child(1)
高。
结语
到这里,文章内容就全部结束了!希望通过这篇文章,能帮助大家更加清晰地掌握 CSS 选择器及其优先级权重的计算方法,无论是在日常开发中解决样式冲突,还是在技术面试中自信应答,都能更加游刃有余。
如果你在阅读过程中发现任何问题或有其他的想法,欢迎交流探讨!也祝正在准备面试的小伙伴们都能拿到自己心仪的 offer,加油!🎉