记录一下之前看到过的CSS样式优先级计算方法。

CSS的样式优先级由一个4位数字权重表示,对于同一个文档元素,如果存在多个样式,就比较每个样式4位数的优先级权重,然后选择值较大的那个。那么这4位数权重是怎么计算的呢?

一般我们添加样式有以下几种方法:

  1. 内联样式 通过style="..."直接将样式加到HTML元素上。如果样式是通过内联方法加上去的,则其权重的千位数字上为1,即1000。

  2. id选择器 在HTML元素上定义id="...",然后在HTML文档内部或者外部CSS文件中通过id选择器来加样式。对于id选择器加上去的样式,其权重的百位数字上为1,即0100。

  3. 类选择器 在HTML元素上定义class="...",然后在HTML文档内部或者外部CSS文件中通过类选择器来加样式。对于类选择器加上去的样式,其权重的十位数字上为1,即0010。

  4. 元素选择器 在HTML文档内部或者外部CSS文件中通过HTML元素选择器来加样式。对于元素选择器加上去的样式,其权重的个位数字上为1,即0001。

样式类型 内联样式 id选择器 类选择器 元素选择器
权重 1000 0100 0010 0001

所以我们可以得出,对于样式优先级,内联样式 > id选择器 > 类选择器 > 元素选择器。如果多个样式类型同时匹配,则将所有类型的权重值累加。我们来看几个栗子:

<html>
  <head>
    <style type="text/css">
        #title {
             /* id选择器,权重为100 */
             color: blue;
        }

        .desc {
             /* 类选择器,权重为10 */
             color: green;
        }

        .desc p {
             /* 类选择器与元素选择器组合,权重为10+1=11 */
             color: yellow;
        }

        .desc div p {
             /* 类选择器与两个元素选择器组合,权重为10+1+1=12 */
             color: grey;
        }
    </style>
  </head>
  <body>
     <!-- 内联样式,权重为1000 -->
     <h1 id="title" style="color: red">Hello World</h1>
     <div class="desc section">
       <div class="paragraph">
         <p><span>This is a hello world page</span></p>
       </div>
     </div>
  </body>
</html>

大家测试一下,就会发现,h1字样是红色的,因为它上面有两种样式,一个是内联样式,权重1000,另一个是id选择器样式,权重100。自然内联样式优先级高,所以显示红色。而段落内文字显示灰色,因为样式选择器.desc div p有一个类选择器和两个元素选择器组合,权重是12,比其他的都高,所以选用它所指定的灰色字体。

到目前为止,很好理解吧。那如果两种样式的权重一样呢。那就看哪个样式离当前元素最近,比如我们把上例最后一个选择器.desc div p中的p去掉:

        .desc p {
             /* 类选择器与元素选择器组合,权重为10+1=11 */
             color: yellow;
        }
        .desc div {
             /* 类选择器与元素选择器组合,权重为10+1=11 */
             color: grey;
        }

现在两个选择器权重都一样,哪个优先级高呢。因为我们的段落文字在”div > div > p > span”下,所以p元素选择器比div选择器离我们的文字更近,因此文字就会显示黄色,而不是灰色。

我们再尝试加个类选择器:

        .desc .paragraph {
             /* 两个类选择器组合,权重为10+10=20 */
             color: pink;
        }

此时权重为20,理论上比其他的几个选择器权重都高,但是浏览器还是优先选择.desc div p的样式,因为这个样式离文字更近。所以可以得出结论,从父元素继承的样式比子元素样式的优先级低。

换一个尝试,我们在所有样式定义的最后加上下面这个选择器:

        .section div p {
             /* 类选择器与两个元素选择器组合,权重为10+1+1=12 */
             color: pink;
        }

.section div p.desc div p优先级一样,都是12,位置也都在元素p上,为啥显示粉色呢?如果我们将代码中两个选择器定义的位置换一下,是不是就变成灰色了?果然如此,原来优先级相同样式,后定义的会覆盖先定义的。

最后,我们来说下!important,如果在上例的id选择器中,加上!important关键字:

        #title {
             /* id选择器,权重为100 */
             color: blue !important;
        }

你会发现h1字样从红色变为了蓝色,看来!important高于所有优先级权重。那如果我们在内联样式中也加上!important呢?结果又是红色了,对于两个!important样式,那就回到原来的权重规则来判断选取哪个样式。

哦,还忘了一种情况,如果我们在Javascript里添加样式会怎么样?

    <script type="text/javascript">
        var ele = document.getElementById('title');
        ele.style.color="orange";
    </script>

我们把上面代码放到HTML Body的最后,不然的话,有些DOM元素还未渲染完毕,document.getElementById()将获取不到元素。打开页面,你会看到h1字体变橙色了。因为上面的代码相当于加上了内联样式,而且是在HTML元素定义之后加的,所以后面的内联样式覆盖了原来的内联样式。但是如果你之前的样式定义里有!important关键字,那就不会覆盖,因为我们说过!important高于所有优先级权重。

总结下CSS样式优先级规则:

  1. 子元素的样式优于从父元素那里继承过来的样式
  2. 同一元素上加的样式,!important样式优先级最大
  3. 如果都是!important或都没!important,则根据上文介绍的优先级计算公式,算出4位优先级权重,然后选取值较大的样式
  4. 如果优先级权重相同,则后面定义的样式覆盖前面定义的