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>

    寫文章不容易,有問題請指出不要踩好嗎,感謝大家。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章