iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 14
2

在學選擇器時,不免會一直提到權重,權重是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.

行內樣式與 !important

選擇器範圍的權重我們已經知道了,但還有比選擇器權重更高的樣式宣告:

  • 行內樣式宣告

    還記得我們在學習套用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.

    權重的筆記到此結束,下篇就開始來介紹各種樣式吧,明天見~/images/emoticon/emoticon41.gif

    *有任何錯誤或描述不夠精準之處,歡迎指教,非常感謝。


上一篇
Day13 CSS selector (3)
下一篇
Day15 CSS基本樣式-color
系列文
從門外漢到前端新手30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Titangene
iT邦新手 4 級 ‧ 2019-09-30 09:26:07

範例超讚!直觀!

JinWen iT邦新手 5 級 ‧ 2019-10-12 16:18:13 檢舉

感謝回饋/images/emoticon/emoticon25.gif

我要留言

立即登入留言