跳轉到

建立 2025-02-25 更新 2026-09-11

層疊、繼承與優先權(Cascade & Specificity)

同一元素被多條規則打到時,瀏覽器不是「隨便選一條」,而是依 層疊(Cascade) 決定勝負:來源 → 層 → 優先權 → 出現順序。搞懂這件事,就不用到處灑 !important

繼承(Inheritance)

有些屬性會從父元素傳到子元素,例如 colorfont-familyline-heightmarginpaddingborderwidth 不會繼承。

article {
  color: #222;
  font-family: "Noto Sans TC", sans-serif;
}

article h2 {
  /* 文字顏色與字體跟著 article,不必重寫 */
  margin-top: 1.5em; /* margin 不繼承,要自己設 */
}

強制控制繼承:

關鍵字 意義
inherit 用父元素的計算值
initial 該屬性的初始值
unset 可繼承屬性當 inherit,否則當 initial
revert 回到瀏覽器/使用者樣式

層疊(Cascade)比的是什麼

由高到低大致是:

  1. 來源:瀏覽器預設 < 使用者樣式 < 作者樣式(你寫的 CSS)
  2. !important:作者的 !important 通常壓過普通規則(使用者 !important 更強,這裡少遇)
  3. @layer 順序:越晚定義的 layer 越強;未進 layer 的作者樣式更強
  4. 優先權(specificity)
  5. 原始順序:權重相同時,後面的贏

層疊比對順序:來源與 important、layer、specificity、程式碼先後

優先權(Specificity)怎麼算

習慣寫成 (inline, id, class, type) 四個數字,由左往右比,不是十進位相加。

來源 權重 例子
行內 style="" (1, 0, 0, 0) style="color: black"
ID (0, 1, 0, 0) #header
class、屬性、偽類 (0, 0, 1, 0) .title[type]:hover
元素、偽元素 (0, 0, 0, 1) h1::before
萬用、:where()、組合符號 (0, 0, 0, 0) *>:where(h1)

:not():is():has() 的權重,取括號裡權重最高的那項;:where() 永遠是 0。

選擇器 權重 誰贏
p (0, 0, 0, 1) 最低
.title (0, 0, 1, 0) 贏過元素
p.title (0, 0, 1, 1) 贏過單獨 .title
#hero (0, 1, 0, 0) 贏過 class
#hero.title (0, 1, 1, 0) 更高
行內 style (1, 0, 0, 0) 一般規則幾乎蓋不掉
#main h1 { color: red; }   /* (0, 1, 0, 1) */
h1.title { color: blue; }  /* (0, 0, 1, 1) */
/* h1 會是紅色:ID 那一欄已經比較大 */

!important

p { color: blue !important; }

它會跳過普通優先權比較,讓除錯變困難。合理用途只有:

  • 覆蓋第三方套件且暫時抽不出更精準的選擇器
  • 工具 class(例如 .hidden { display: none !important; }

不要用 !important 修選擇器戰爭

正確做法是降低選擇器權重(多用 class、少用 id)、或把公用樣式放進 @layer

@layer(建議專案一開始就用)

把「重置、主題、元件」分開,後面的 layer 覆蓋前面的,不必靠更長的選擇器

@layer reset, tokens, components, utilities;

@layer tokens {
  :root { --text: #222; }
}

@layer components {
  .btn { padding: 0.5rem 1rem; }
}

@layer utilities {
  .mt-0 { margin-top: 0; }
}

未放入任何 layer 的作者 CSS,會蓋過所有 layer。這讓「偶爾的頁面覆寫」仍然好寫。

實務原則

  1. 元件樣式用 單一 class.card.btn),不要 div.wrapper > ul > li > a
  2. 狀態用修飾 class:.btn.is-active,權重只多一個 class
  3. 需要「很容易被蓋」的預設時用 :where()
  4. 權重打平時,把覆寫寫在後面,或抽成更後面的 layer

總結

  • 可繼承的多半是文字相關屬性;盒子相關屬性要自己設。
  • 勝負順序:來源 / !important@layer → specificity → 先後。
  • 行內 > ID > class > 元素;:where() 權重為 0。
  • !important 是最後手段。

下一步進入 盒模型,看元素實際佔掉多少空間。