css样式顺序覆盖方式及权重计算详解

写在前面

在用Django写一个项目时,由于多个网页一些元素的css样式是重复的,所以就写了该元素的一般样式,比如a标签在很多页面都会出现,我们就把这些页面的a标签共同样式写到css中。当某个页面中a标签和一般样式不一样的时候我们就需要重写a标签的样式来覆盖原来的一般样式。这看似简单,但是当你的标签里的内容写复杂了之后,你就容易混淆了。
我一个做后台的,之前学习的时候找了半天都找不到我想要的,都是些最基本的使用,最后竟还是自己debug解决的,所以写下这篇比较详细的博客希望对和我一样有需要的人有所帮助。

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,用.来判别:

    <style>
        .contain{
            width: 200px;
            height: 200px;
            margin: 0 auto;
            background: #F7F7F7;
        }
    </style>
    <body>
        <div class="contain" id="content"></div>
    </body>
  • 标签类型和伪元素选择器,权重量级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;,修改为如下:

    <style>
        #users_info .user_name{/*权重:100*1+10*1=110*/
            font-size: 15px;
            color: #1B6D85;
        }
        .user #username{/*权重:100*1+10*1=110*/
            font-size: 14px;
            color: #333333;
        }
    </style>
  • 问题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文件中的样式,原因就是<link rel="stylesheet" href="css/test.css"></link>后引用,后引用会覆盖先引用的(前面说过)。我们修改如下顺序就可以让它为<style></style>中的样式了:

    <link rel="stylesheet" href="css/test.css"></link>
    <style>
        #users_info .user_name{/*权重:100*1+10*1=110*/
            font-size: 15px;
            color: #1B6D85;
        }
    </style>
  • 问题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>
  • 问题5:跳级引用,跳过标签的缩少对样式有影响吗?

    答案是没有影响,.c_1 a跳了一级标签但是毫无影响,两个都是包含一个类,一个标签,所以样式看两个的先后顺序:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title></title>
        </head>
        <style>
            .c_1 a{/*权重:x*1+y*1*/
                font-size: 19px;
                color: #8A6D3B;
            }
            .c_2 a{/*权重:x*1+y*1*/
                font-size: 21px;
                color: #F0AD4E;
            }
        </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">
                        <a>注意我的字体大小和颜色</a>
                    </div>
                </div> 
            </div>
        </body>
    </html>

    写文章不容易,有问题请指出不要踩好吗,感谢大家。

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值