What is CSS Specificity ?


對一個CSS 新手來說,我最常遇到的問題就是:

我明明有把這個 div 顏色從紅色變成藍色啊,為什麼沒有改變呢?

…原來這都是因為不了解 CSS Specificity 的關係啦!今天就來分享一下~


為什麼選不到我要的CSS選擇器?

“Somewhere among your CSS rules, you’ve defined a more specific selector.”

因為在你寫的 CSS 規則中,你定義了一個更具體/詳細的選擇器!

→ 簡單來說,越具體/詳細的定義CSS選擇器,他的權重就越高。所以當兩個選擇器都選到同一個元素,瀏覽器就會套用權重較高的選擇器。

可是怎麼知道怎樣定義才算詳細/具體呢?這就要看他的 specificity value。就讓我們來了解一下吧!


4 Categories of Specificity Hierarchy

在計算 specificity value 前,先來了解一下 Specificity Hierarchy。每個選擇器都能被歸納進以下四類的其中一類。

  • Inline styles (行內樣式) <h1 style="color: #fff;">
  • IDs #myDiv
  • Classes, attributes, pseudo-classes (類別,屬性,偽類別) 
     — classes .topic 
     — attributes input[data-value="foo"] 
     — pseudo-classes :hover, :focus
  • elements and pseudo-elements (元素與偽元素)
     — elements div, li 
     — pseudo-elements :before, :after

Calculating Specificity Value

在知道有這四種類型以後,我們開始來計算 specificity value 吧!
 — 以下引用 Specificity Calculator 來截圖做解釋 —

MORE Specificity → LESS Specificity

上面這四個區塊就是前面提到的 Specificity Hierarchy 的那四類。
Specificity Value 的計算方式很簡單,就是用數的
怎麼數呢?我們來看看幾個例子:

#Example 1

先來一個常寫的範例。.container 是一個 class, :hover 是一個 pseudo-class, 所以藍色的那一類有2個。ul 和 li 都是 elements,所以綠色那類有2個。
 → 所以 .container ul li:hover {} 的 specificity value 就是 0,0,2,2。
(也可以把四個數字當成一般數字來看: 0,0,2,2 → 22)

#Example 2

再來看一個範例。#nav 是 ID,所以 ID 那類(粉色的)有1個。.selected 是 class, :hover 是 pseudo-class,所以藍色那類有2個。ul,li,a 都是 elements,所以綠色那類有3個。
 → 所以 ul#nav li.selected > a:hover {} 的 specificity value 就是 0,1,2,3。

#Example 3 (這個example 來自 CSS-Tricks )

來看一個特別的範例。#footer 是 ID,所以 ID 有1個。nav 和 li 都是 element,所以綠色那類有兩個。這邊比較特別的是,注意到星號(*) universal selector 他沒有被歸類到以下四類的任何一類喔,所以他也就不能被計算。再來就是 :not() 是一個偽類別選擇器,但比較特別,所以也不能被計算,只有:not(nav) 裡面的 nav 就有被計算喔。
 → 所以 #footer *:not(nav) li 的 specificity value 就是 0,1,0,2。

#Example 4

<div style="background-color: #ff0;"></div>

→ inline style 被使用的時候,他的 specificity value 就是 1,0,0,0。

— —

從以上4個例子來比較,specificity value 從最高到最低

Ex 4 (1,0,0,0) > Ex 2 (0,1,2,3) > Ex 3 (0,1,0,2) > Ex 1 (0,0,2,2)

— —

以下這張圖有更多範例做為參考

(圖片來源:Smashing Magazine’s Specificity Example

Specificity : Basic Principle

  • 當兩個選擇器的 specificity value 一樣的時候,就會看他們在code裡的順序。也就是說,後面的才被採用。
  • (*) universal selector 的 specificity value → (0,0,0,0),也就是說,他沒有 specificity value。
  • :not() 偽類別不會影響 specificity value,是他()裡面的選擇器才會影響。
  • !important 的 specificity value 最大,只要使用它,一定會覆蓋掉其他沒有使用 !important 的選擇器。

希望透過這次的分享可以幫助到目前還在為 CSS Specificity 煩惱的 CSS 新手們~以後我們不會再不懂為什麼選不到我們要的選擇器了!


Additional Resources

Show your support

Clapping shows how much you appreciated Bonnie Wu’s story.