CSS 优先级和权重

@一棵菜菜  August 4, 2019

前言

之前写页面样式时,有时会遇到用多条样式定义规则对同一个元素进行样式设置的时候,当时想到的就是按CSS选择器的优先级来搞定这个问题,也就只记得:内嵌样式 > id > class > 标签 这样简单的规则,虽然基本可以搞定需求,也自以为然的就是这个样子了,但是最近发现原来这部分还要更深层次的内容,所以今天专门学习了下。


CSS 选择器

概念:用来指定该组 CSS 样式会对什么元素生效的,是连接 HTML 结构和 CSS 样式的桥梁。

我的思维导图-CSS选择器
CSS选择器集合请点击查看此文

一、什么是权重

权重,是一个相对的概念,是针对某一指标而言。某一指标的权重是指该指标在整体评价中的相对重要程度

每一个CSS的选择器都有一个相对的重要程度值,也就是权重的值,简称“权值”;

CSS通过CSS选择器的权重占比,来计算CSS选择规则的总权值,从而确定 定义样式规则的 优先级次序;

从“CSS权重的理解”中得知,原来所谓为的 CSS选择规则的优先级 是按照 CSS选择器的权值的比较 来确定的。


二、什么是优先级

此部分摘抄自MDN《CSS优先级》

优先级是基于不同种类 选择器 组成的匹配规则
浏览器通过 优先级 来判断哪些属性值与一个元素最为相关,从而在该元素上应用这些属性值。

2.1 优先级是如何计算的?

优先级就是分配给指定的CSS声明的一个权重,它由 匹配的选择器中的 每一种选择器类型的 数值 决定。

而当优先级与多个CSS声明中任意一个声明的优先级相等的时候,CSS中最后的那个声明将会被应用到元素上。

【牢记】当同一个元素有多个声明的时候,优先级才会有意义。因为每一个 直接作用于元素的CSS规则 总是会覆盖(take over)该元素从祖先元素 继承 而来的规则 (例子见文末第九部分)。

2.2 注意!important:

当在一个样式声明中使用一个!important 规则时,此声明将覆盖任何其他声明。虽然技术上!important 与优先级无关,但它与它直接相关

使用 !important 是一个坏习惯,应该尽量避免!因为这破坏了样式表中的固有的级联规则 使得调试找bug变得更加困难了。当两条相互冲突的带有 !important 规则的声明被应用到相同的元素上时,拥有更大优先级的声明将会被采用。

三、CSS优先级规则小结【牢记】

  1. CSS选择规则的权值不同时,权值高的优先;

    先从高等级进行比较,高等级相同时,再比较低等级的,以此类推(而不是直接求权值总和来比较大小)!
  2. CSS选择规则的权值相同时,后定义的规则优先(也就是样式覆盖);
  3. CSS属性后面加 !important 时,无条件绝对优先((比内联样式还要优先));

四、权值等级划分【牢记】

CSS选择器的权值等级划分图:

权值计算.png

一般来说是划分4个等级:

  1. 第一等级:代表 内联样式,如 style="",权值为1000;
  2. 第二等级:代表 ID选择器,如 #id="", 权值为100;
  3. 第三等级:代表 calss | 伪类 | 属性 选择器,如 .class | :hover,:link,:target | [type], 权值为10;
  4. 第四等级:代表 标签 | 伪元素 选择器,如 p | ::after, ::before, ::fist-inline, ::selection, 权值为1;
注意:
通配选择符(*), 关系选择符 (+(相邻同胞选择器), >(子选择器), ~, ' ') 和 否定伪类(:not()) 对优先级没有影响。(但是,在 :not() 内部声明的选择器是会影响优先级)。

部分关系选择符:

  • div>p 选择所有父级是 <div> 元素的 <p> 元素(父子关系)
  • div+p 选择所有紧接着<div>元素之后的<p>元素。(div后面的第一个p,同级或叫兄弟关系)
  • div~p 选择<div>元素之后的每一个<p>元素(同级或叫兄弟关系)

:not()例子:

// 样式1
div.outer p {
  color:orange;
}
// 样式2
div:not(.outer) p {
  color: red;
}

<div class="outer">
  <p>A : This is in the outer div.</p>
  <div class="inner">
    <p>B : This text is in the inner div.</p>
  </div>
</div>
:not 否定伪类在优先级计算中不会被看作是伪类. 事实上, 在计算选择器数量时还是会把其中的选择器当做普通选择器进行计数.
结果为:A行颜色为orange,B行为red。
注意:若把样式1、样式2位置交换,由于两个的权值完全相同,所以后者优先,A、B颜色都为orange。

五、权值计算公式

权值 = 第一等级选择器*个数,第二等级选择器*个数,第三等级选择器*个数,第四等级选择器*个数

六、 权值比较规则

当两个权值进行比较的时候,是从高到低逐级将等级位上的权重值(如 权值 1000 对应--> 第一等级权重值,第二等级权重值,第三等级权重值,第四等级权重值)来进行比较的,而不是简单的 1000个数 + 100个数 + 10个数 + 1个数 的总和来进行比较的

换句话说:低等级的选择器,个数再多也不会越等级超过高等级的选择器的优先级的!

类比理解:古代丞相再多,也超不过一个皇帝的~
【为什么这么特别强调呢,因为为在网上查资料的时候,看到好多博客是把这个权重值理解成了所有等级的数字之和了】,说到这里 再 配合下图 大家应该就差不多理解了,

七、验证第三部分的'CSS优先级规则'

1. 验证第一点:

<!DOCTYPE html>
<html>
<head>
    <title>CSS 选择器</title>
    <style type="text/CSS">
/*
        1.先从高等级进行比较,高等级相同时,再比较低等级的,以此类推.
        2.完全相同的话,就采用 后者优先原则(也就是样式覆盖),
        3.有 !important 时,无条件绝对优先

        如下面的 示例:
     */
        /* qz1权值: 0,100,0,1 */
        #parent p {
            background-color: red;  
        }
        /*qz2权值: 0,0,10*11,1*2 */
        div .a.b.c.d.e.f.g.h.i.j.k p{ 
            background-color: green;  
        }
      /* qz3权值:0,0,10*11,1*2 */
      div .a .b .c .d .e .f .g .h .i .j .k p { 
        background-color: orange;
      }
    </style>
</head>
  <body>
    <div id="parent">
      <div class="a b c d e f g h i j k">
        <p>p-11</p>
      </div>
      <div class="a">
        <div class="b">
          <div class="c">
            <div class="d">
              <div class="e">
                <div class="f">
                  <div class="g">
                    <div class="h">
                      <div class="i">
                        <div class="j">
                          <div class="k"><p>p-22</p></div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
    </div>
  </body>
</html>
如果对CSS权重理解不透彻的话,看到上边的例子,估计会有很大一部分人都会认为最后 p-11 的背景色是 green; 为什么呢? 因为理解成了错误的权值计算规则:
qz1 = 100 + 1 = 101
qz2 = 1 + 10*11 + 1 = 112
qz1 < qz2,所以 第二条样式 优先级高,背景色为 green;

NO,NO,NO....结果却是 背景色为 red!
实际分析为:
qz1 = 第二等级权值100,第三等级权值0,第四等级权值 1
qz2 = 第二等级权值0, 第三等级权值 10*11 = 110,第四等级权值1*2
因qz1第二等级权值> qz2第二等级权值,所以第一条样式优先级更高,所以背景色为 red.

p-22 也是红色,因为qz1第二等级权值> qz3第二等级权值,所以第一条样式优先级更高。

2. 验证第二点

<!DOCTYPE html>
<html>
<head>
    <title>CSS 选择器</title>
    <style type="text/CSS">
    /*
        1.先从高等级进行比较,高等级相同时,再比较低等级的,以此类推.
        2.完全相同的话,就采用 后者优先原则(也就是样式覆盖),
        3.有 !important 时,无条件绝对优先

        如下面的 示例:
     */
        #parent #child1 {background-color: red;} /* 权值: 0,200,0,0; */
        #parent #child1 {background-color: green;} /* 权值: 0,200,0,0; */
    </style>
</head>
<body>
    <div id="parent">
        <div id="child1">xxxxxx</div> 
    </div>
</body>
</html>
结果为green.

3. 验证第三点

<!DOCTYPE html>
<html>
<head>
    <title>CSS 选择器</title>
    <style type="text/CSS">
    /*
        1.先从高等级进行比较,高等级相同时,再比较低等级的,以此类推.
        2.完全相同的话,就采用 后者优先原则(也就是样式覆盖),
        3.有 !important 时,无条件绝对优先

        如下面的 示例:
     */
        #parent div#child1 { background-color: yellow !important;  } /* !important 无条件绝对优先 */
        #parent div#child1 {background-color: red;} /* 权值: 0,200,0,1; */
        #parent #child1 {background-color: green;} /* 权值: 0,200,0,0; */
    </style>
</head>
<body>
    <div id="parent">
        <!-- 权值:1, 0, 0, 0 -->
        <div id="child1" style="background-color:orange;">xxxxxx</div>
        <div id="child2">xxxxxx</div>
    </div>
</body>
</html>
如果没有 !important 的样式规则时,相信大家都知道内联样式的优先级是最高的,背景色为 orange;
加了!important 之后,没有任何理由的 它的优先级就最高了,背景色为 yellow。

八、单个选择器的优先级

通过上边的分析,我们就得出了单个选择器的优先级比较:

  • CSS属性!important
  • >(大于) 内联样式
  • > ID选择器(#id)
  • > 类选择器(.class) = 伪类选择器(:hover等) = 属性选择器(如[type=text]等]
  • > 元素选择器(p等) = 伪元素选择器(:after/:before/::selection等)
  • > 通用选择器(*)
  • > 继承的样式
关于伪类的部分,这篇文章总结还挺好的(尤其是 :not(选择器) 伪类不参与优先级计算,但:not(选择器) 里边的 “选择器” 是参与优先级计算的 这部分),可参考:

  地址:https://www.cnblogs.com/starof/p/4387525.html


九、直接给目标元素添加样式和目标元素继承样式对比

继承是一种机制,它允许样式不仅可以应用于某个特定的元素,还可以应用于它的后代
例子:

<style type="text/CSS">
#close{
    color: green;
}
#further{
    color: purple;
}
p {
    color: red;
}
</style>

<body>
    <div id="further">
      <div>caicai</div> // purple,继承自 #further
      <div id="close">
        <h1>Here is a title!</h1> // green,继承自 #close
      </div>
      <p>hello</p> // red,来自 p
    </div>
</body>
不管#close和#further顺序,h1文字都是 green 的,他们是作用在不同的div上的,h1继承了#close的color。
若没有 p 选择器,则 hello 默认继承 #further 选择器定义的样式,但因为 p 选择器是明确的定位到了元素,优先级:element > 继承的,所以 p定义的样式覆盖了继承自#futher定义的样式,则 hello 颜色为 red。
牢记:"当同一个元素有多个声明的时候,优先级才会有意义",否则如果只是继承,那离的近的当然优先级高!

我的小结

1.(作用)浏览器通过 优先级 来判断哪些属性值(CSS样式)最终应用在该元素上,而优先级是基于不同种类 选择器 组成的匹配规则。这里有一个”权重“的概念,权重表示相对重要程度。每个CSS的选择器都有一个相对的重要程度值,也就是权重的值,简称“权值”。简而言之,CSS 优先级 就是按照 CSS 选择器的权值比较 来确定的。

2.CSS 选择器的权值等级划为:
style内联样式(1000),id(100),class-伪类-属性选择器(10),element-伪元素选择器(1)

3.CSS 优先级规则(各等级权值分别比较,而非简单地把所有权值相加比较总和):

  1. 先从高等级的权值进行比较,权值高的优先;但若高等级相同时,再比较低等级的,以此类推;
  2. 各等级权值完全相同的话,就采用 后者优先原则(也就是样式覆盖);
  3. !important 时,无条件绝对优先(虽然技术上!important 与优先级无关,但它与它直接相关)
注意:低等级的选择器,个数再多也不会越等级超过高等级选择器的优先级的!

4.当同一个元素有多个声明的时候,优先级才会有意义!因为每一个 直接作用于元素的 CSS 规则 总是会覆盖(take over)该元素从祖先元素 继承 而来的规则

5.所以也就有了常说的优先级:!important > style内联样式 > id选择器 > class > element > 继承的。


其他

非常推荐文章《CSS的优先级 和 权重》
官方文档MDN《CSS优先级》
CSS选择器集合
我的思维导图-CSS选择器

添加新评论