CSS选择器的权重与优先规则

一般而言,大多数前端工程师对css样式优先级的概念停留在如下所示:

注:>表示优先级的一个高低,|表示优先级一样

!important>行间样式>id>class|属性>标签选择器>通配符

但实际上,css是有一个权重的。且是可也计算的,

我们在使用CSS对网页元素定义样式时经常会遇到这种情况:要对一般元素应用一般样式,然后在更特殊的元素上覆盖它们。那么我们怎么样来保证我们所新定义的元素样式能覆盖目标元素上原有的样式呢?

在CSS中,会根据选择器的特殊性来决定所定义的样式规则的次序,具有更特殊选择器的规则优先于具有一般选择器的规则,如果两个规则的特殊性相同,那么后定义的规则优先(这点很重要,这点很重要,这点很重要,也就是你定义的样式,比如在css文件中,写在后面的样式会覆盖前面的样式,因为引用样式的时候是按照顺序导入的,它会将一个标签对应找到的所有样式加载,后加载的如果和前面的重复就会覆盖前面的样式)。

我们把特殊性分为4个等级,我们首先得知道这个,这个等级并不代表你最后样式得引用顺序,我们需要在这个等级得基础上能判断出样式得引用顺序,4个等级如下:

  • 内联样式,权重量级1000(1000这个数是不对的,只是为了好计算,见问题4)。

内联样式是定义在html的标签中的,如下的style属性,直接嵌入到div标签里:

<div class="contain" id="content" style="width: 200px;height: 200px;margin: 0 auto;background: #C4E3F3;"></div>
  • ID选择器,权重量级100(100这个数是不对的,只是为了好计算,见问题4)。

通过id来引用样式,可以写在css文件中,也可以写在html中,在html中需要使用 <style></style> 括起来,在css文件中就不用,id前面使用#来判别:

<style>
    #content{
        width: 200px;
        height: 200px;
        margin: 0 auto;
        background: #333333;
    }
</style>
<body>
    <div class="contain" id="content"></div>
</body>
  • 类、伪类、属性选择器,权重量级10(10这个数是不对的,只是为了好计算,见问题4)。

同ID,用.来判别

  • 标签类型和伪元素选择器,权重量级1(1这个数是不对的,只是为了好计算,见问题4)。
  • <style>
        body{
            width: 200px;
            height: 200px;
            margin: 0 auto;
            background: #333333;
        }
    </style>
    <body>
        <div class="contain" id="content"></div>
    </body>
    

    计算示例

你的样式权重和你的写法有很大关系,对应到同一个标签写法不同,样式的权重就不同,如下:

​
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <style>
        #username{/*权重:100*1=100*/
            font-size: 14px;
            color: #333333;
        }
        #users_info #username{/*权重:100*2=200*/
            font-size: 15px;
            color: #1B6D85;
        }
        #users_info a{/*权重:100*1+1=101*/
            font-size: 16px;
            color: #398439;
        }
        .user_info #username{/*权重:100*1+10*1=110*/
            font-size: 17px;
            color: #66512C;
        }
        .user_info a{/*权重:10*1+1*1=11*/
            font-size: 18px;
            color: #843534;
        }
        #in_block .user_info #username{/*权重:100*2+10*1=210*/
            font-size: 19px;
            color: #8A6D3B;
        }
        .contain #in_block .user_info #username{/*权重:100*2+10*2=220*/
            font-size: 20px;
            color: #C7254E;
        }
        #content #in_block .user_info a{/*权重:100*2+10*1+1*1=211*/
            font-size: 21px;
            color: #F0AD4E;
        }
    </style>
    <body>
        <div class="contain" id="content" style="width: 200px;height: 200px;margin: 0 auto;background: #C4E3F3;">
            <div id="in_block" class="left_content">
                <div class="user_info" id="users_info">
                    <a id="username">注意我的字体大小和颜色</a>
                </div>
            </div>
        </div>
    </body>
</html>


​

根据上面权重的计算可以知道不同写法样式引用顺序不同,权重越小会先引用,后面权重大的样式如果出现和前面相同的属性就会把之前的覆盖掉。这里由于样式都是字体和颜色的样式,所以后面的会完全覆盖掉先引用的。很明显最后的样式是权重为220的那个,如果我现在在权重为11的样式中加入font-family: "微软雅黑";是不会被覆盖的,因为后面的都没有出现font-family这个属性。要知道上面的所有样式都会被加载,只是出现重复定义的属性才会根据权重大小来覆盖重复的属性。
 

问题解决

问题1:权重相同的两个样式都映射到一个标签,哪一个会被覆盖呢?

这就是除去权重后的又一个影响因素了,权重相同就和你的书写顺序有关了,写在前面的会被后面的覆盖,注意是前面被后面覆盖掉,如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <style>
        .user #username{/*权重:100*1+10*1=110*/
            font-size: 14px;
            color: #333333;
        }
        #users_info .user_name{/*权重:100*1+10*1=110*/
            font-size: 15px;
            color: #1B6D85;
        }
    </style>
    <body>
        <div class="contain" id="content" style="width: 200px;height: 200px;margin: 0 auto;background: #C4E3F3;">
            <div id="in_block" class="left_content">
                <div class="user" id="users_info">
                    <a class="user_name" id="username">注意我的字体大小和颜色</a>
                </div>
            </div>
        </div>
    </body>
</html>

最后的样式会是font-size: 15px;color: #1B6D85;,先定义先加载,先加载就很可能被后面的覆盖。修改顺序样式就会改变为font-size: 14px;color: #333333;

问题2:权重相同,一个样式定义在html中一个定义在css文件中,哪一个会被覆盖呢?

样式会和你的引入顺序有关,在html中通过<style></style>定义的样式实际上就是引入的css文件,只不过这个文件已经在html中,不用再去走加载css文件这一步。所以你的引入顺序决定了你的样式,如下    

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <style>
        #users_info .user_name{/*权重:100*1+10*1=110*/
            font-size: 15px;
            color: #1B6D85;
        }
    </style>
    <link rel="stylesheet" href="css/test.css"></link>
    <body>
        <div class="contain" id="content" style="width: 200px;height: 200px;margin: 0 auto;background: #C4E3F3;">
            <div id="in_block" class="left_content">
                <div class="user" id="users_info">
                    <a class="user_name" id="username">注意我的字体大小和颜色</a>
                </div>
            </div>
        </div>
    </body>
</html>

test.css:

.user #username{/*权重:100*1+10*1=110*/
    font-size: 14px;
    color: #333333;
}

虽然权重一样,但是由于test.css引人顺序在style标签后,所以后加载覆盖了前面style标签里的,最后显示的是test.css中的样式

问题3:同一个标签有多个类名来修饰,类名的先后顺序对样式有影响吗?

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <style>
        .left_posion{/*权重:10*1=10*/
            font-size: 17px;
            color: #67B168;
        }
        .name_font{/*权重:10*1=10*/
            font-size: 16px;
            color: #000000;
        }
        .user_name{/*权重:10*1=10*/
                font-size: 15px;
                color: #1B6D85;
            }
    </style>
    <body>
        <div class="contain" id="content" style="width: 200px;height: 200px;margin: 0 auto;background: #C4E3F3;">
            <div id="in_block" class="left_content">
                <div class="user" id="users_info">
                    <a class="user_name name_font left_posion" id="username">注意我的字体大小和颜色</a>
                </div>
            </div>
        </div>
    </body>
</html>

最后的样式为.user_name的样式,也就是说class="user_name name_font left_posion"的三个类是同级的,没有区别,只和你样式的权重和写的顺序有关。

问题4:(id、类、标签)的权重量级真的就是(100、10、1)吗?

答案是否定的,如下,根据前面的计算方式明显111大于101,可是使用的样式却是#username a的,说明前面说的什么量级1000、100、10、1都是错的,这里特别指出,几个类别是没有具体的值,它的区分方法是先看类别,假设我包含id,你不包含,那我就能覆盖你,如果你也包含id那就比个数,个数多的覆盖个数少的,个数一样就同理再看包含的类,再看标签个数,如果id、类、标签的个数都相同就看写的顺序(以下代码只是我为了说明100不是定数,一般不会写十一个类来定位标签样式。。。):

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <style>
        .contain .c_1 .c_2 .c_3 .c_4 .c_5 .c_6 .c_7 .c_8 .c_9 .c_10 a{/*权重:10*11+1*1=111*/
            font-size: 21px;
            color: #F0AD4E;
        }
        #username a{/*权重:100*1+1*1=101*/
            font-size: 19px;
            color: #8A6D3B;
        }

    </style>
    <body>
        <div class="contain" id="content" style="width: 200px;height: 200px;margin: 0 auto;background: #C4E3F3;">
            <div class="c_1">
                <div class="c_2">
                    <div class="c_3">
                        <div class="c_4">
                            <div class="c_5">
                                <div class="c_6">
                                    <div class="c_7">
                                        <div class="c_8">
                                            <div class="c_9">
                                                <div class="c_10"
                                                    <div class="c_1" id="username">
                                                        <a>注意我的字体大小和颜色</a>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div> 
        </div>
    </body>
</html>


学习参考:https://blog.csdn.net/youand_me/article/details/79015946

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值