在學選擇器時,不免會一直提到權重,權重是css的樣式聲明的套用比較級,當很多樣式被寫在同一個css檔時,它們的權重值會決定誰最後勝出,元素最終會以權重值最高的樣式聲明來渲染。
權重是以權重值來判定輸贏,權重值越高的樣式聲明勝出,作為元素的套用樣式。在CSS規範裡,權重值的計算方式描述如下:
- count the number of ID selectors in the selector (= a)
- count the number of class selectors, attributes selectors, and pseudo-classes in the selector (= b)
- count the number of type selectors and pseudo-elements in the selector (= c)
- ignore the universal selector
上列描述,將權重值的計算分成三個權級:
a. ID 選擇器
b. 類別選擇器、屬性選擇器、偽類選擇器
c. 元素選擇器、偽元素選擇器
d. 任何元素選擇符*
沒有權級
而a >b >c >d
所以我們知道了偽類被歸類為跟類別選擇器同一個權集,偽元素跟元素選擇器同一個權級。就是為什麼上一篇講到:root
權重比html
高的原因,因為:root
偽類比html
元素高一個權級。
權重值的表示通常為(ID, class, element),也就是:
element selector ( 0 ,0, 1)
class selector ( 0, 1, 0)
ID selector ( 1, 0, 0)
如果在vsCode裡將游標移到選擇器上,也會顯示當下選擇器的權重值。可以看到下圖的
.container
為class selector,權重值就會是( 0, 1, 0):
藉上述規則,我們可以用範例來驗證:
html
<body>
<h1 class="special" id="uniq">I am an H1</h1>
</body>
css
h1 {color: red} /*權重值(0, 0, 1)*/
body h1 {color: green} /*權重值(0, 0, 2)*/
h1.special { color: blue} /*權重值(0, 1, 1)*/
#uniq{ color: orange} /*權重值(1, 0, 0)*/
權重值( 1, 0, 0) > 權重值( 0, 1, 1) > 權重值( 0, 0, 2) > 權重值( 0, 0, 1)
所以最後是由ID選擇器勝出,而顯示橘色。
渲染結果
Try it on codepen.
各位注意到了嗎?雖然 body h1
的權重值,因為寫了兩個元素,所以為(0, 0, 2),但並不意味著它的數值2會大於類別選擇器跟ID選擇器的數值1 ; 它們的數值只會在同個權級比較而已,若是不同權級,數值再大也大不過高的權級。
點 Specificity Caculator 試試各種選擇器的權重。
html
<main class="test fun">
<div>
<h1>I am an H1</h1>
<h2>I am an H2</h2>
<h2>I am an H2</h2>
</div>
</main>
css
.test div > h2 { color: green;} /*權重值(0, 1, 2)*/
.fun h1 ~ h2 { color: red;} /*權重值(0, 1, 2)*/
渲染結果,雖然兩個權重值相等,可是後來聲明的樣式會蓋過前面的樣式聲明。
Try it on codepen.
選擇器範圍的權重我們已經知道了,但還有比選擇器權重更高的樣式宣告:
行內樣式宣告
還記得我們在學習套用CSS時,有講到直接把樣式寫在html元素內嗎?行內樣式宣告的權重是大於選擇器的權重值的。
html:直接在<h1>
元素內寫入粉紅色的樣式。
<body>
<h1 style="color: pink;" class="special" id="uniq">I am an H1</h1>
</body>
css
h1 {color: red} /*權重值(0, 0, 1)*/
body h1 {color: green} /*權重值(0, 0, 2)*/
h1.special { color: blue} /*權重值(0, 1, 1)*/
#uniq{ color: orange} /*權重值(1, 0, 0)*/
渲染結果:CSS選擇器所寫的宣告沒有一個被套用,全都內行內樣式蓋過去。
Try it on codepen.
!important
!important有點像是打破了選擇器的層級概念, 直接提出一個異義一樣,這個異議聲明會強迫瀏覽器套用它所指定的樣式,通常會避免這樣的做法,因為若想用其它方式蓋掉是沒辦法的。!important的語法是寫在樣式聲明列的後面,但要在結束符;
分號之前。
html
<body>
<h1 style="color: pink; class="special" id="uniq">I am an H1</h1>
</body
css 在權重值最低的第一行樣式聲明,提出異議聲明!important。
h1 {color: red !important;} /*權重值(0, 0, 1)*/
body h1 {color: green;} /*權重值(0, 0, 2)*/
h1.special { color: blue;} /*權重值(0, 1, 1)*/
#uniq{ color: orange;} /*權重值(1, 0, 0)*/
渲染結果 不管原本聲明的權重值是多少,也不管行內樣式是什麼,important強迫瀏覽器渲染它所指定的樣式列。
Try it on codepen.
*有任何錯誤或描述不夠精準之處,歡迎指教,非常感謝。