紀錄工作經驗、相關知識,解決技術相關問題。

CSS, HTML, 新手 Jamp Holes, 網站相關, 資訊相關

CSS 權重計算規則:!important、ID 與 Class 優先順序與 Cascading 層疊邏輯

CSS 權重計算規則:!important、ID 與 Class 優先順序與 Cascading 層疊邏輯 特色圖片

新手在寫網頁時最常遇到的困擾就是:「為什麼我明明寫了 color: blue;,畫面上的文字卻還是紅色的?」這正是因為還不熟悉 CSS 權重與優先順序(Specificity 與 Cascading)。繼第一章介紹 CSS 基礎語法架構:選擇器規則、樣式載入方式與屬性聲明實作 後,本篇將透過簡單的權重計分表與 4 個實例,帶你一眼看懂哪一條 CSS 規則會勝出。


一、 CSS 權重(Specificity)分數計算與層疊判斷維度

當多條 CSS 規則同時選中同一個 HTML 元素時,瀏覽器會依照以下 3 個層疊(Cascading)判斷維度 進行篩選,若前一個維度無法分出勝負,才會進入下一個維度:

  1. 來源(Origin):樣式來自於瀏覽器預設、使用者自訂、還是開發者撰寫的 CSS。
  2. 權重(Specificity):根據選擇器的具體程度計算分數(見下方表格)。
  3. 順序(Order):若以上兩者皆相同,則以樣式表內「後定義者」為準。

CSS 權重分數計算對照表

瀏覽器會依照以下 5 個等級的權重分數 由高到低決定誰能生效:

優先級排名選擇器類型權重座標表示 (A, B, C, D)語法範例
最高!important 強制標記超越所有選擇器權重color: blue !important;
第 1 級行內樣式(Inline Style)(1, 0, 0, 0) (1000 分)style="color: red;"
第 2 級ID 選擇器(0, 1, 0, 0) (100 分)#main-title
第 3 級Class、屬性與偽類選擇器(0, 0, 1, 0) (10 分).highlight、[type="text"]
第 4 級(最低)HTML 元素與偽元素選擇器(0, 0, 0, 1) (1 分)h1、div、::before

(註:通用選擇器 *、組合符號 >、+、~ 以及否定偽類 :not() 本身皆為 0 分;而 :where() 偽類包住的選擇器權重也永遠為 0 分。)


二、 4 個實例看懂 CSS 優先順序與覆蓋規則

範例 1:基本權重對決(HTML 標籤 vs Class 選擇器)

當 h1 元素同時擁有 .highlight 類別時,文字顏色會顯示為藍色,因為 .highlight 的權重 (0,0,1,0) 高於 h1 的 (0,0,0,1)。

h1 { color: red; }        /* 權重 (0, 0, 0, 1) */
.highlight { color: blue; } /* 權重 (0, 0, 1, 0) */

範例 2:複合選擇器權重累加(ID vs 元素 + Class 組合)

ID 選擇器 (0,1,0,0) 的等級永遠高於再多個 Class 與標籤的組合。即使組合選擇器寫得再長,也無法撼動 ID 的優先權。

#main-title { color: green; }      /* 權重 (0, 1, 0, 0) */
h1.highlight { color: blue; }     /* 權重 (0, 0, 1, 1) */

範例 3:!important 強制覆蓋

在 CSS 屬性值後方加上 !important 時,該條屬性會擁有最高優先權,直接無視前面提到的 ID 或行內樣式權重。

.highlight { color: blue !important; }
#main-title { color: green; } /* 被 !important 覆蓋 */

範例 4:相同權重下的原始碼先後順序

當兩條規則的選擇器權重完全相同時,在 CSS 檔案裡寫在比較後面的那一條規則會勝出。

.highlight { color: blue; }
.highlight { color: green; } /* 最終顯示綠色 */

三、 現代 CSS 特性:Cascade Layers (@layer)

為了避免權重戰爭,現代 CSS 引入了 @layer。它允許開發者定義樣式的「優先級層級」,定義在後面的 @layer 具有更高的層疊優先權,這與選擇器本身的權重分數無關。

/* 定義層級順序:base 為底層,utilities 為高層 */
@layer base, utilities;

@layer base {
  h1 { color: red; } /* 即使權重低,也會被 utilities 層覆蓋 */
}

@layer utilities {
  h1 { color: blue; }
}

四、 常見問題與排錯 Q&A

Q1:在 HTML 的 class="box1 box2" 中,box2 寫在後面就會覆蓋 box1 嗎?

  • 問題原因:樣式誰蓋誰,看的是 「.box1 和 .box2 在 .css 樣式表檔案裡的先後順序」,跟 HTML class="..." 裡面誰排前面、誰排後面完全無關!
  • 解決思路:若希望某個狀態 Class(如 .is-active)能覆蓋基礎 Class(.btn),請確保在 CSS 檔案中將 .is-active 寫在 .btn 的下方。

Q2:為什麼專案裡不建議到處亂加 !important?

  • 問題原因:一旦加上 !important,未來寫 RWD 響應式網頁 或特定頁面微調時,你寫的所有普通選擇器都會失效,只能被迫用更多 !important 去互蓋,導致樣式表難以維護,甚至造成日後無法覆蓋的維護災難。
  • 解決思路:優先透過「提高一層父層 Class 選擇器(如 .card .title)」來自然提升權重,盡量避免動用 !important。

Q3:如何透過「重複 Class」增加權重?

  • 問題原因:有時候我們無法修改 HTML 結構,但又需要提升某個 Class 的權重來覆蓋外部樣式。
  • 解決思路:可以透過重複撰寫相同的 Class 名稱來疊加權重(每個 Class 權重為 10 分)。例如 .btn.btn.btn 的權重為 30,這會高於單一的 .btn(10 分),這是一個在不使用 !important 的前提下,微調權重的實務技巧。

參考資料與延伸閱讀

發佈留言