當前位置: 妍妍網 > 碼農

關於 CSS 選擇器權重,99% 的人都理解錯了!

2024-05-07碼農

CSS 選擇器的權重(特異性)是確定在多個選擇器套用於同一元素時,哪個選擇器的樣式會最終生效的關鍵因素。然而,關於 CSS 選擇器特異性的理解,常常存在一些常見的誤解。本文將探討這些誤解,並幫助大家理解 CSS 選擇器的權重。

誤解一:權重是一個數位

CSS 選擇器的權重並不是一些數位。所以,計算元素的權重時,並不是簡單的將權重數值相加就可以了。

CSS 選擇器的權重由三個部份組成,表示為 (a, b, c),其中 a、b、c 分別代表了不同選擇器型別的權重。具體規則如下:

  • ID選擇器 :權重值為(1, 0, 0),透過元素的ID選擇器來匹配的樣式。

  • 類選擇器、內容選擇器和偽類選擇器 :權重值為(0, 1, 0),類選擇器(如 .example )、內容選擇器(如 [type="text"] )和偽類選擇器(如 :hover )具有相同的權重。

  • 元素選擇器和偽元素選擇器 :權重值為(0, 0, 1),元素選擇器(如 p )和偽元素選擇器(如 ::before )具有相同的權重。

  • 註意 :通配符選擇器(如 *)、子選擇器(如 >)、相鄰兄弟選擇器(如 +)和兄弟選擇器(如 ~)對權重沒有貢獻,即它們的權重為 (0,0,0)。

    權重計算規則

    1. 從左到右進行比較 :首先比較最高位(行內樣式),如果相同,則比較下一位,依此類推。例如(1, 0, 0)的優先級高於(0, 1, 0),而(0, 1, 0)的優先級高於(0, 0, 1)。

    2. 權重相加 :每個組成部份的權重是獨立計算的,並且 不會累加 。比如,一個選擇器中有兩個類選擇器( . class1. class2 )並不會使其權重變為(0,2,0),而是仍然保持為(0,1,0)。同樣,一個選擇器中有一個ID選擇器和一個類選擇器( #id. class )的權重是(1,1,0),而不是(2,0,0)。

    3. !important 規則 :如果在聲明中使用了 !important ,它會覆蓋其他所有的特異性。但需要註意的是, !important 只在同一來源的樣式中有效。如果來自使用者代理樣式表(瀏覽器預設樣式)或使用者樣式表的 !important 規則與來自作者樣式表的普通規則沖突,那麽使用者代理樣式表或使用者樣式表的 !important 規則會生效。

    4. 來源順序 :如果兩個規則的特異性相同,並且都沒有使用 !important ,那麽後出現的規則會覆蓋先出現的規則(即「後來者居上」的原則)。

    例如:

    /* 權重為 (0,0,1) */
    div{color:red;}
    /* 權重為 (0,1,0) */
    . class1{color:green;}
    /* 權重為(1,0,0) */
    #id1{color:blue;}
    /* 權重為(1,1,0)(因為 ID 選擇器的權重高於類選擇器)*/
    #id1. class1{color:purple;}
    /* 權重為(0,1,0),因為只有一個類選擇器 */
    . class1{color:red;}
    /* 權重為(0,1,0),即使有兩個類選擇器,但它們的權重不會相加 */
    . class1. class2{color:blue;}
    /* 權重為(1,1,0),因為一個ID選擇器和一個類選擇器的組合 */
    #id1. class1{color:green;}
    /* 權重為(0,1,0),因為有三個類選擇器,但每個類選擇器的權重仍然是(0,1,0) */
    . class1. class2. class3{color:purple;}

    在上面的例子中,即使選擇器中包含多個相同的組成部份(如類選擇器),每個組成部份的權重仍然是獨立的,並且不會累加。因此,在選擇器沖突時,特異性更高的選擇器將覆蓋特異性較低的選擇器。如果特異性相同,則後出現的規則會覆蓋先出現的規則(即「後來者居上」的原則)。

    詳細來看看最後一個例子:

    對於選擇器 . class1. class2. class3 ,其特異性(權重)的計算方式如下:

  • 該選擇器包含三個類選擇器(. class1、. class2 和 . class3)。

  • 在CSS特異性計算中,每個類選擇器都貢獻(0,1,0)的特異性值。

  • 由於特異性值不會跨型別累加,我們只需關註類選擇器這一位(即第三位)上的數量。

  • 在這個例子中,有三個類選擇器,但每個類選擇器在類選擇器這一位上的值仍然是 1。

  • 但是,這並不意味著三個類選擇器加起來就是 3。實際上,在選擇器的特異性計算中,我們不會將類選擇器這一位上的值相加。我們只需記錄存在多少個類選擇器(在這個例子中是三個)。然而,在描述特異性時,我們通常(0,3,0)不直接寫出這樣的表示法,因為按照標準的特異性表示法,我們只需指出在類選擇器這一位上有三個單位(即 0,1,0 出現了三次)。

    但是,為了明確和避免混淆,當我們談論這種由多個同類選擇器組成的選擇器的特異性時,我們可能會說它在類選擇器這一位上的特異性「權重」相當於(0,3,0)(盡管這不是標準的表示法)。不過,在比較選擇器的特異性時,我們只需記住它在類選擇器這一位上有三個單位。

    因此, . class1. class2. class3 的特異性(權重)按照標準的表示法是 (0,1,0)(但因為有三個類選擇器,所以在類選擇器這一位上的「等效權重」可以理解為三個單位)。

    誤解二:使用 style內容會增加權重

    很多人認為,在 HTML 元素上直接使用 style內容來定義 CSS 樣式會增加樣式權重。

    在 HTML 元素上直接使用 style 內容並不會增加元素的特異性。實際上, style 內容定義的樣式具有最高的優先級,這通常被稱為「行內樣式」或「行內樣式」。但這種高優先級並非來源於特異性的計算,而是源於CSS層疊和沖突解決機制中的一個特殊規則。

    CSS層疊的優先級規則中, style 內容(行內樣式)的優先級高於其他任何在樣式表中定義的樣式規則,無論這些樣式規則使用了何種選擇器(ID、類、元素等)。但請註意,這種優先級與特異性是兩個不同的概念。

  • 特異性 :用來確定哪些樣式規則會套用到元素上的機制。特異性是一個由三個部份組成的權重值當兩個或更多的樣式規則都適用於同一個元素時,瀏覽器會根據這些規則的特異性來決定哪個規則會最終套用到該元素上。

  • 優先級 :在特異性相同的情況下,用來確定哪個樣式規則會生效的機制。這時,會按照以下順序來確定優先級,在優先級上,使用者樣式會覆蓋使用者代理樣式,而作者樣式會覆蓋使用者樣式(除非使用者樣式使用了 !important ):

  • 行內樣式

  • 作者的樣式表

  • 重要的作者樣式

  • 普通的作者樣式

  • 使用者代理樣式(User Agent stylesheet):瀏覽器的預設樣式,如預設字型大小、顏色等。

  • 使用者樣式(User styles):透過瀏覽器設定或擴充套件自訂的樣式。

  • 作者樣式(Author styles):在樣式表中定義的樣式。

  • 在作者定義的樣式中,行內樣式具有最高的優先級,即使其他樣式規則具有更高的特異性。但請註意,這並不意味著行內樣式具有更高的特異性;它只是在優先級上高於其他樣式。因此, style 內容並不會增加元素的權重。

    誤解三:使用!important會增加權重

    我們知道,在 CSS 中使用 !important 會使得樣式的優先級最高。不過,在 CSS 聲明中使用 !important 並不會增加其特異性。

    特異性(權重)是一個由選擇器型別決定的權重系統,用於確定在多個樣式規則套用於同一元素時,哪個規則會被優先套用。而 !important 則是一個覆蓋機制,用於改變聲明的優先級,使其在CSS的層疊順序中具有更高的權重。

    當瀏覽器需要確定一個元素的最終樣式時,它會按照以下步驟進行:

    1. 計算特異性 :首先,瀏覽器會計算每個套用於該元素的 CSS 規則的特異性。特異性越高的規則,其優先級越高。

    2. 比較來源 :如果兩個或多個規則具有相同的特異性,瀏覽器會進一步比較這些規則的來源。通常,使用者定義的樣式(如瀏覽器擴充套件或使用者樣式表)會覆蓋作者定義的樣式(即網頁開發者的樣式表),而作者定義的樣式會覆蓋使用者代理樣式(即瀏覽器的預設樣式)。

    3. 考慮!important :如果兩個或多個規則具有相同的特異性和來源,並且其中至少有一個使用了 !important ,則使用了 !important 的規則會覆蓋沒有使用 !important 的規則。

    4. 比較順序 :如果兩個或多個規則具有相同的特異性、來源,並且都沒有使用 !important ,或者都使用了 !important ,則最後定義的規則會覆蓋先前定義的規則。

    因此, !important 並不改變特異性,而是在特異性比較之後,作為一個額外的優先級判斷依據。使用 !important 應該謹慎,因為它會破壞CSS的層疊和特異性規則,使得樣式更難於維護和偵錯。在可能的情況下,最好透過最佳化選擇器和組織樣式規則來避免使用 !important