寫Web的人或多或少對CSS有一些了解,知道CSS Selector(如#id, .className, div.className)在套用上會採取愈具針對性愈優先的原則,所以當多組Style設定衝突時,指定#id比指定.className優先,指定.className的規則又比只指定div優先。用個具體例子來說明,以下<div>中的文字是什麼顏色?

排版顯示純文字
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>CSS Specificity</title>
    <style type="text/css">
        #d { color: Orange }
        .clsName { color: Yellow }
        div { color: Green }
    </style>
</head>
<body>
    <div id="d" class="clsName" style="color: Red">Text</div>
</body>
</html>

因為 element style > #d > .clsName > div,所以由style=”color: Red”勝出,文字是紅色的。若將style="color: Red”移除,則由#d做主變成橘色;將#d規則移除後換.clsName當家變成黃色;把.clsName也拿掉,才輪到div決定綠色。

這是比較簡單的例子。那如果是下面的情況呢?

排版顯示純文字
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>CSS Specificity</title>
    <style type="text/css">
        #d1 { color: Blue }
        div#d1 { color: Red }
        #d1.clsName { color: Orange }
        div.clsName { color: Green }
        
        span .c3 { color: Red }
        .c1 span { color: Green }
        .c2 span { color: Purple }
        span span.c3 { color: Blue }
    </style>
</head>
<body>
    <div id="d1" class="clsName">不算難</div>
    <span id="d2" class="c1 c2">
        <span id="d3" class="c3">好機車</span>
    </span>
</body>
</html>

"不算難"還好猜,可推測 #d1.clasName > div#d1 > #d1,所以是橘色。但"好機車"的藍色要怎麼推算出來?

在W3C的CSS 2.1規格中定義了Selector的a-b-c-d套用法則(術語叫Selector’s Specificity):

  • count 1 if the declaration is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules. These rules have no selectors, so a=1, b=0, c=0, and d=0.)
  • count the number of ID attributes in the selector (= b)
  • count the number of other attributes and pseudo-classes in the selector (= c)
  • count the number of element names and pseudo-elements in the selector (= d)

W3C的文件還附上了詳細的範例(節錄於下),應該不難理解:

 *             {}  /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */
 li            {}  /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */
 li:first-line {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
 ul li         {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
 ul ol+li      {}  /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */
 h1 + *[rel=up]{}  /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */
 ul ol li.red  {}  /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */
 li.red.level  {}  /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */
 #x34y         {}  /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */
 style=""          /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */

比較順序時,先比a,a大的勝出;若a相同再比較b,以此類推。(規格原文說in a number system with a large base,可以想像成a * 1000^3 + b * 1000^2 + c * 1000 + d)

回到好機車的例子:

span .c3 { color: Red } => a=0 b=0 c=1 d=1
.c1 span { colro: Green } => a=0 b=0 c=1 d=1
.c2 span { color: Purple } => a=0 b=0 c=1 d=1
span span.c3 { color: Blue } => a=0 b=0 c=1 d=2

這解釋了為什麼最後由span span.c3決定藍色。但值得注意的是,span .c3、.c1 span、.c2 span都是c=1, d=1,若由這三者對決,.c1/.c2會優於span,而.c2比.c1晚出現,最後將會由.c2 span封王--紫色。,三者優先權相同,以後出現者為準,本例為紫色,若將 span .c3 移到最下方則會是紅色。


Comments

# by 阿呆

span .c2、.c1 span、.c2 span都是c=1, d=1,若由這三者對決,.c1/.c2會優於span,而.c2比.c1晚出現,最後將會由.c2 span封王--紫色 -------------------------------------------------- .c1/.c2會優於span <- 這句是錯的,三者的優先權都一樣,就看誰最後出現,就採用那種設定.所以說,如果span .c3 { color: Red } 寫在最後,就會是紅色

# by Jeffrey

to 阿呆,你是對的,span .c3 與 .c2 span 優先權相同,以後出現者為準,已修正本文。感謝指正。

# by fruitbear

真的好機車(笑)

Post a comment