「CSS Specificity」相關筆記
重點整理
- 有重複的 CSS 樣式規則套用到同一個 HTML 元素上的時候,權重(specificity)高的樣式會覆蓋權重低的樣式設定。
- 原始碼中位置越下方(後發)的 CSS 樣式會複寫先寫出來的樣式。
- 樣式規則有衝突的時候,權重較高的樣式會覆蓋權重低的樣式。衝突規則的權重一樣大的時候,後發的樣式會覆蓋先寫的樣式。
Specificity
Specificity(以降以「權重」稱之)的高低影響哪一些 CSS 樣式會發生作用。 設定好的 CSS 沒有作用,可能就是 CSS 樣式的權重沒有妥善安排,導致編寫好的 CSS 樣式沒有如預期般套用到 HTML 元素上。
權重從低至高順位分組如下:
-
universal selector 與 inherited style:使用
*
選取「全部」與繼承得來的樣式,兩者的權重皆為0-0-0-0-0
;最低的權重 -
element selector、::pseudo-element selector:選取 HTML 元素或偽元素,權重為
0-0-0-0-1
- HTML 元素:html、body、section、div、p……等 HTML 元素(element)
- 偽元素:
A CSS pseudo-element is a keyword added to a selector that lets you style a specific part of the selected element(s).
參考MDN,偽元素指的是 HTML 元素的「某一個部份」,較常見的大概是
::after
、::before
與::first-letter
-
.class selector、:pseudo-class selector、[attribute] selector:選取 class、偽類或具有特定屬性(attribute)的 HTML 元素,權重為
0-0-0-1-0
- 偽類:
A CSS pseudo-class is a keyword added to a selector that specifies a special state of the selected element(s).
參考MDN,偽類指的是 HTML 元素的「某一種狀態」,最常見的大概是
:hover
- 屬性:參考MDN,以
input[type="checkbox"]
為例,就是「選取所有是 checkbox 特性的 input 元素」
- 偽類:
-
#id selector:選取擁有某 id 的 HTML 元素,權重是
0-0-1-0-0
-
inline style(比如
<p style="color: red;">text</p>
):權重是0-1-0-0-0
,不過這樣會讓原始碼的維護性變差,所以還是避免使用吧 -
!important
:擁有最大的權重1-0-0-0-0
,而後發的!important
會壓過先寫出來的!important
權重的計算方式
參考以上劃分的六種權重分組,將選取器中屬於同一組的選擇器條件相加後進行比大小。
舉個 🌰,假設以下兩種color
的樣式設定位在同一份原始碼裡面:
#blue {
/* 第一組樣式 */
color: blue;
}
div p {
/* 第二組樣式 */
color: red;
}
而 HTML 內容如下:
<div>
<p id="blue">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Consectetur,
magnam!
</p>
</div>
第一組樣式的選取器為#id 一個,權重為:0-0-1-0-0
第二組樣式的選取器為 HTML 元素兩個,權重為:0-0-0-0-2
第一組樣式的權重大於第二組,故以上的<p>
會是藍色:
See the Pen css specificity by Charlie (@Charlie7779) on CodePen.
需注意的是,CSS 的權重並不是十進位制,選取五十個.class 做出來的 CSS 樣式也比不過選取一個#id 宣告出來的樣式。
舉個 🌰,假設以下兩種background-color
的樣式設定位在同一份原始碼裡面:
#yellow {
background-color: yellow;
}
.c1 .c2 .c3 .c4 .c5 .c6 .c7 .c8 .c9 .c10 .c11 {
background-color: green;
}
而 HTML 內容如下:
<div class="c1">
<div class="c2">
<div class="c3">
<div class="c4">
<div class="c5">
<div class="c6">
<div class="c7">
<div class="c8">
<div class="c9">
<div class="c10">
<div class="c11" id="yellow"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
那麼該<div>
的背景顏色會是黃色:
See the Pen css specificity by Charlie (@Charlie7779) on CodePen.
在 CSS Specificity 的宇宙裡,團結起來的五十個.筷子
還是會被#●門
夾爆的。
快速判別樣式的權重
!important
最大,有複數個!important
就看哪一段樣式最後被執行- element 贏不過.class 與[attribute],.class 與[attribute]贏不過#id
- 使用人家寫好的計算機:Specificity Calculator
權重相等時,後發覆蓋先寫的樣式
假設style.css
的內容如下:
p {
color: blue;
}
而 HTML 內容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="./style.css" />
<style>
p {
color: green;
}
</style>
</head>
<body>
<p>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Consectetur,
magnam!
</p>
</body>
</html>
因為<style>
比<link rel="stylesheet" href="./style.css">
晚執行,所以<p>
會是綠色(按下▶執行程式碼看結果):
而如果調換<style>
與<link rel="stylesheet" href="./style.css">
的順序:
<!DOCTYPE html>
<html lang="en">
<head>
<style>
p {
color: green;
}
</style>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<p>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Consectetur,
magnam!
</p>
</body>
</html>
<p>
就會是藍色(按下▶執行程式碼看結果):
LVHA
問:為什麼超連結的 CSS 樣式最好以「link-visited-hover-active」的順序從上到下書寫? 答:因為樣式權重相等的時候,後發的樣式會覆蓋先寫的內容。 假設使用「link-hover-active-visited」的順序來設定 CSS 樣式:
a:link {
color: blue;
}
a:hover {
color: aqua;
}
a:active {
color: red;
}
a:visited {
color: purple;
}
那一個被點擊過的(:visited
)超連結,即使在:hover
或:active
的狀態,也不會被套上:hover
或:active
的樣式,因為:hover
與:active
通通被:visited
的樣式蓋過去了。
點擊過以下範例的超連結後,即使把游標停留在連結上,文字也不會變為水藍色:
See the Pen LHAV by Charlie (@Charlie7779) on CodePen.
但如果把樣式順序修改如下:
a:link {
color: blue;
}
a:visited {
color: purple;
}
a:hover {
color: aqua;
}
a:active {
color: red;
}
這個超連結就可以表現出四種不同狀態的樣式。
先點擊以下範例的超連結,超連結的文字會變成紫色,但因為:hover
與:active
的樣式順序在:visited
以下,所以當游標停留在連結上(狀態為:hover
)時,文字會變成水藍色;而點下超連結(狀態為:active
)時,文字會變成紅色:
See the Pen LVHA by Charlie (@Charlie7779) on CodePen.
規則衝突時,後發覆蓋先寫的樣式
舉個 🌰,假設以下兩種針對<p>
的樣式設定位在同一份原始碼裡面:
p {
color: red;
background: blue;
}
p {
color: yellow;
}
衝突的規則只有color
,background
不受影響,所以最後<p>
的樣式會是「藍色背景、黃色文字」:
See the Pen css specificity by Charlie (@Charlie7779) on CodePen.
透過繼承得到的樣式,權重是 0-0-0-0-0
舉個 🌰,假設以下兩種樣式設定位在同一份原始碼裡面:
#parent {
color: green;
}
h1 {
color: red;
}
而 HTML 內容如下:
<html>
<body id="parent">
<h1>A Title</h1>
</body>
</html>
<h1>
從<body id="parent">
繼承到的文字色彩樣式會被 CSS 樣式表中的h1
覆蓋掉(樣式h1
的權重是 0-0-0-0-1),<h1>A Title</h1>
會是紅色:
See the Pen inherited styles by Charlie (@Charlie7779) on CodePen.