在前端面试中,经常会遇到CSS选择器的问题三连:
我们在上一篇 【前端基础系列】CSS篇-常用选择器介绍 中已经对问题1进行了详细的解答,今天就来给大家介绍选择器的优先级和权重计算方式。里面关于一些权重比较误区的介绍,大家千万不要错过。
先提出一个问题:如果一个元素通过多种方式设置了字体大小,那么浏览器在最后渲染时会使用哪个属性值呢?
其实,浏览器会通过优先级来判断哪些属性值与一个元素最为相关,从而在该元素上应用这些属性值。优先级是基于不同种类选择器组成的匹配规则。
换种说法,优先级就是分配给指定的 CSS 声明的一个权重,它由 匹配的选择器 中的 每一种选择器类型的数值 决定。
总结一下:
接着介绍权重的计算规则:
!important
会覆盖页面内任何位置的元素样式style="color: green"
,权值为1000#app
,权值为0100.foo
, :first-child
, div[class="foo"]
,权值为0010div::first-line
,权值为0001*, >, +
,权值为0000权值计算公式:
权值
=第一等级选择器
x个数
,第二等级选择器
x个数
,第三等级选择器
x个数
,第四等级选择器
x个数
比如:
选择器 | 千位 | 百位 | 十位 | 个位 | 优先级 |
---|---|---|---|---|---|
h1 | 0 | 0 | 0 | 1 | 0001 |
h1 + p::first-letter | 0 | 0 | 0 | 3 | 0003 |
li > a[href*="en-US"] > .inline-warning | 0 | 0 | 2 | 2 | 0022 |
#identifier | 0 | 1 | 0 | 0 | 0100 |
内联样式 | 1 | 0 | 0 | 0 | 1000 |
当两个权值进行比较的时候,是从高到低逐级将等级位上的权重值(如 权值 1,0,0,0 对应--> 第一等级权重值,第二等级权重值,第三等级权重值,第四等级权重值)来进行比较的,而不是简单的 1000个数 + 100个数 + 10个数 + 1个数 的总和来进行比较的,换句话说,低等级的选择器,个数再多也不会越等级超过高等级的选择器的优先级的。
下面通过几个例子进行比较规则的说明。
假设下面样式都作用于同一个节点元素span
,判断下面哪个样式会生效
body#god div.dad span.son {width: 200px;}
body#god span#test {width: 250px;}
比较规则说明:
#god
= 100#god
+ #text
= 200width: 250px;
<style type="text/css">
#parent p { background-color: red; }
div .a.b.c.d.e.f.g.h.i.j.k p{ background-color: green;
</style>
......
<div id="parent">
<div class="a b c d e f g h i j k">
<p>xxxx</p>
</div>
</div>
如果按照相加的错误方法,如果按照相加的规则的话,上述例子会为:
qz1 = 100 + 1 = 101
qz2 = 1 + 10*11 + 1 = 112
qz1 < qz2
这样得出结论:第二条样式优先级高,背景色为 green
。
但结果却是 red
,这也证明了权重是按优先级进行比较的。
总结下比较规则:
行内>id>class>元素(标签)
,我们以为给了能令面试官满意的答案,其实不然,比如对同一个元素操作,在权重相等的情况下,后面的样式会覆盖前面的,这样我们给出来的答案就不成立了当在一个样式声明中使用一个 !important
规则时,此声明将覆盖任何其他声明。
虽然,从技术上讲,!important
与优先级无关,但它与最终的结果直接相关。
使用 !important 是一个坏习惯,应该尽量避免,因为这破坏了样式表中的固有的级联规则,使得调试找bug变得更加困难了。
当两条相互冲突的带有 !important
规则的声明被应用到相同的元素上时,拥有更大优先级的声明将会被采用。
一些经验法则:
最后,我们再来看个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
font-size: 24px;
}
.main {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
p {color: yellowgreen} /* 0,0,0,1 */
.para {color: red} /* 0,0,1,0 */
.inner p {color: pink} /* 0,0,1,1 */
.main p[class*="para"] {color: rgb(0, 255, 115)} /* 0,0,2,0 */ /*权重相同,后者覆盖前者*/
.main p[class="para1"] {color:teal} /* 0,0,2,0 */
div.main p[class="para2"]{color: blueviolet;} /* 0,0,2,1 */
.inner p:nth-child(4) {color: cornflowerblue !important;} /*0,0,2,0, !important提升优先级*/
</style>
</head>
<body>
<div class="main">
<div id="app" class="inner" >
<p style="color: red;">我是红色的,内联样式生效</p>
<p class="para1">离离原上草,</p>
<p class="para2">一岁一枯荣。</p>
<p class="para3">野火烧不尽,</p>
<p class="para4">春风吹又生。</p>
</div>
</div>
</body>
</html>
样式呈现的效果如下:
《前端面试题宝典》经过近一年的迭代,现已推出 小程序
和 电脑版刷题网站 (https://fe.ecool.fun/
),欢迎大家使用~
同时,我们还推出了面试辅导的增值服务,可以为大家提供 “简历指导” 和 “模拟面试” 服务,现在参与还有额外优惠,感兴趣的同学可以联系小助手(微信号:interview-fe)进行体验。