優先權

CSS Podcast - 003:Specificity

假設您使用的是以下 HTML 和 CSS:

<button class="branding">Hello, Specificity!</button>
.branding {
  color: blue;
}

button {
  color: red;
}

這裡有兩個規則會指定相同的元素。每項規則都包含要設定按鈕顏色的宣告:一個嘗試將按鈕設為紅色,另一個則嘗試將按鈕設為藍色。哪個宣告會套用至元素?

瞭解 CSS 特殊性演算法,是理解 CSS 如何在競爭宣告之間做出決定的關鍵。

特定性是分層處理的其中一個階段,我們在上一單元介紹了分層處理

特異性評分

來源中的每個選取器規則都會獲得評分。您可以將特定性視為總分,而每個選取器類型都會為該分數賺取積分。宣告會優先採用最具體的規則。

在實際專案中,您需要取得平衡,確保您要套用的 CSS 規則確實「套用」,同時盡量維持低分數以避免複雜性。特異性應只設為所需的程度,而非設為盡可能高的程度。日後,您可能需要套用一些更重要的 CSS。如果您追求最高的專一性,就會讓這項工作變得困難。

優先權不是小數,而是由 ABC 三個元件組成的三重奏。

  • A:類似 ID 的特定性
  • B:類別式特異性
  • C:元素類型特異性

通常會使用 (A,B,C) 符號表示。例如:(1,0,2)。您也可以使用 A-B-C 代碼。

圖表顯示特異性的三個要素 (A、B、C)。每個元件都會在圖表中顯示其代表意義,以及影響該元件的選取器範例。
圖表說明各種選取器會影響哪些特定元件。

比較特徵

比較特徵時,會依序比較三個元件:A 值越大,特徵越明確;如果兩個 A 值相同,則 B 值越大,特徵越明確;如果兩個 B 值也相同,則 C 值越大,特徵越明確;如果所有值都相同,則兩個特徵相同。

舉例來說,(1,0,0) 的專一性高於 (0,4,3),因為 (1,0,0) 中的 A 值 (即 1) 大於 (0,4,3) 中的 A 值 (即 0)。

選取器會影響特異性

特徵三元組中的每個部分開頭都會以 0 的值開始,因此預設特徵為 (0,0,0)。選取器的每個部分都會提高特異性,並根據選取器類型增加 ABC 的值。

通用選取器

通用選取器 (*) 不會新增任何特異性,其值會維持在 (0,0,0) 的初始特異性。

* {
  color: red;
}

元素或擬元素選取器

元素 (類型) 或擬元素選取器會新增類似元素的特定性,將 C 元件增加 1

以下範例的整體特異性為 (0,0,1)

類型選取器

div {
  color: red;
}

擬造元素選取器

::selection {
  color: red;
}

類別、擬似類別或屬性選取器

類別擬造類別屬性選取器會新增類別式特異性,將 B 元件增加 1

以下範例的特異性為 (0,1,0)

類別選取器

.my-class {
  color: red;
}

擬造類別選取器

:hover {
  color: red;
}

屬性選取器

[href='#'] {
  color: red;
}

ID 選取器

ID 選取器會新增 類似 ID 的特定性,只要您使用 ID 選取器 (#myID) 而非屬性選取器 ([id="myID"]),即可將 C 元件增加 1。

在以下範例中,特異性為 (1,0,0)

#myID {
  color: red;
}

其他選取器

CSS 有許多選取器。但並非所有都會增加具體性。舉例來說,:not() 擬似類別本身不會對特異性計算做出任何貢獻。

不過,傳入做為引數的選取器會加入到特異性計算中。

div:not(.my-class) {
  color: red;
}

這個範例的特定性為 (0,1,1),因為它有一個類型選取器 (div) 和一個 :not() 內部的類別。

進行隨堂測驗

測驗您對特定性評分標準的瞭解程度

a[href="#"] 的專一性為何?

(0,0,1)
a 的價值為 (0,0,1),但 [href="#"] 的價值為 (0,1,0)
(0,1,0)
請再試一次!a 的價值為 (0,0,1),但 [href="#"] 的價值為 (0,1,0)
(0,1,1)
a 的值為 (0,0,1)[href="#"] 的值為 (0,1,1),因此總特異性為 (0,1,1)

不會影響特異性的因素

以下是一些常見的迷思,關於影響特異性的因素。

內嵌樣式屬性

直接套用至元素 style 屬性的 CSS 不會影響特異性,因為這是級聯中評估特異性之前的不同步驟。

<div style="color: red"></div>

如要在樣式表單中覆寫這項宣告,您必須在連鎖的早期步驟中使用宣告勝出。

舉例來說,您可以將 !important 新增至其中,讓該檔案成為已授權的 !important 來源的一部分。

!important 項宣告

CSS 宣告結尾的 !important 不會影響特異性,但會將宣告放入不同的來源,也就是已著作權 !important

在以下範例中,.my-class 的特定性與 !important 宣告的勝出無關。

.my-class {
  color: red !important;
  color: white;
}

如果兩個宣告都是 !important,則又會再次使用特異性,因為級聯的來源步驟尚未能判定勝出者。

.branding {
  color: blue !important;
}

button {
  color: red !important;
}

特定內容

使用複雜或複合選取器時,該選取器的每個部分都會增加特異性。請參考以下 HTML 範例:

<a class="my-class another-class" href="#">A link</a>

這個連結包含兩個類別。以下 CSS 中的規則具有 (0,0,1) 的特定性

a {
  color: red;
}

如果您在選取器中參照其中一個類別,現在該類別具有(0,1,1)的特定性:

a.my-class {
  color: green;
}

將其他類別新增至選取器,現在它具有 (0,2,1) 的特定性

a.my-class.another-class {
  color: rebeccapurple;
}

在選取器中加入 href 屬性,現在的特定性為 (0,3,1)

a.my-class.another-class[href] {
  color: goldenrod;
}

最後,請將 :hover 擬類別新增至所有這些內容,選取器最終會以 (0,4,1) 的特定性結尾:

a.my-class.another-class[href]:hover {
  color: lightgrey;
}

進行隨堂測驗

測驗您對特定性評分標準的瞭解程度

下列哪個選取器的特定性為 (0,2,1)

article > section
元素會新增元素類型特定性 (`C` 元件)。選取器中有 2 個元素,因此其特異性為 (0,0,2)
article.card.dark
元素會新增元素類型的特定性 (C 元件),而類別會新增類別類型的特定性 (B 元件)。由於有 2 個類別和 1 個元素,因此這個選取器的特異性為 (0,2,1)
article:hover a[href]
元素會新增元素類型的特定性 (`C` 元件),而擬似類別和屬性則會新增類別類型的特定性 (`B` 元件)。這個選取器包含 2 個元素選取器 (2 個 (0,0,1))、1 個屬性選取器 (價值 (0,0,1)) 和 1 個類別選取器 (價值 (0,0,1)),因此總特異性為 (0,2,2)

務實提高精確度

假設您有以下 CSS:

.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

使用以下 HTML 程式碼:

<button class="my-button" onclick="alert('hello')">Click me</button>

按鈕的背景為灰色,因為第二個選取器具有 (0,1,1) 的特定性。這是因為它有一個類型選取器 (button),即 (0,0,1),以及一個屬性選取器 ([onclick]),即 (0,1,0)

先前的規則 .my-button 等於 (0,1,0),因為它有一個類別選取器,比 (0,1,1) 的特定性低。

如要提升此規則的優先順序,您可以重複類別選取器,如下所示:

.my-button.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

由於新選取器會取得特定性 (0,2,0),因此按鈕現在會顯示藍色背景。

若在特定性上出現平手,系統會改為執行分層處理程序中的下一個步驟

我們先繼續使用按鈕範例,並將 CSS 切換為以下內容:

.my-button {
  background: blue;
}

[onclick] {
  background: grey;
}

按鈕的背景為灰色,因為兩個選取器的特異性相同,都是 (0,1,0)

如果您切換來源順序中的規則,按鈕就會變成藍色。

[onclick] {
  background: grey;
}

.my-button {
  background: blue;
}

這是因為兩個選取器具有相同的特異性。在這種情況下,層疊會改為使用顯示順序步驟

資源