原文地址:http://www.denisdeng.com/?p=165
本文節選自《The Ultimate CSS Reference 》一書,翻譯不足之處,請斧正,可參考原書:specificity一節。
初學者可能對優先順序的概念不甚明白,但我們在寫css的時候經常遇到這些問題。優先順序主要是避免樣式聲明中的衝突。當針對同一元素的同一屬性有多個聲明時,並且這些聲明來源相同,權重相同,那麼,更明確的css聲明將佔主導地位。
設想下面這個例子:複製內容到剪貼簿
代碼:
P{
Color:black;
Background-color:white;
}
div.warning p{
color:red;
}
Div#caution p{
Color:yellow;
}
Body#home div p{
Color:white;
}
上面的樣式單中包含四條針對p元素的樣式,它們都包含一條針對color的聲明,瀏覽器需要明確那條聲明會被最終應用,p元素的最終color是什嗎?
答案很簡單,最明確的選取器聲明將佔據上風,瀏覽器通過分析選取器的優先順序,並最終篩選出優先順序最高的聲明。
下面是同一選取器多種聲明的比較過程:
- 如果是在元素的style中聲明元素的屬性,而不是在選取器中進行,毫無疑問,它具有最高的優先順序。如果沒有內聯屬性,進入步驟2;
- 計算選取器的ID,ID數量最多的優先順序最高,如果ID的總數相同或者為0,進入步驟3;
- 計算類屬性(如.test)、屬性選取器(如[type=’submit’])以及偽類 (如:hover)。數量最多的優先順序相對較高,如果總數相同或者為0,進入下一步;
- 計算類型選取器(如div)和虛擬元素(如:first-letter)的個數,總數高的優先順序高。
如果多個選取器具有相同的優先順序,根據級聯樣式單的規則:後來者居上.
W3c講述了計算優先順序的方法,計算結果用四個逗號分開的a,b,c,d矩陣來表示,a中代表的優先順序最高,d代表的是最次要,計算過程如下:
- 聲明來自style的,a=1;
- b,統計ID的個數;
- c,統計屬性選取器、偽類的個數;
- d,統計元素類型和偽類元素的個數。
計算結果不是一個具體的數值,而是可以相互比較的矩陣,回想前面例子中的一條聲明:複製內容到剪貼簿
代碼:
P{
Color:black;
Background-color:white;
}
按照上面的公式,我們得到的是0,0,0,1,因為僅一個元素類型。
正如前面所說,這不是數值,而是一個矩陣,a代表最高的優先順序,d優先順序最低,從左至右,比較每欄的最高值,b欄的值會覆蓋c、d中的值,不論c和d中的值是多少。這樣,0,1,0,0的優先順序將比0,0,10,0高。
我們將計算的步驟拆分開來使之更易於理解。
首先計算a,如果在元素的style中定義其屬性,它的值就為1,否則為0,事實上,a欄的值只有一種情況。
你可以看到,內聯樣式的優先順序為1,0,0,0,例如:引用:
<p style=”color:red;”>red text</p>
這就是問什麼盡量避免使用內聯樣式的原因,因為內聯樣式總是具有最高的優先順序,唯一能改變它的方法是在css中使用!important聲明。
除了內聯樣式,我們需要計算b,c,d。看看下面這條規則的優先順序計算:複製內容到剪貼簿
代碼:
Body#home div#warning p.message{color:red;}
上面的規則用來定義color屬性,既然沒有內聯樣式,第一欄a=0,如下表:
計算b欄中的值,統計ID的數量,上面的選取器中,有兩個ID:#home和#warning,這樣b=2,如下表:
下一步,計算c欄的值,統計類別選取器、屬性選取器、偽類的個數。(註:[id=”foo”與#foo是不相同的])
上面的選取器中,有一個類別選取器.message,所以c=1,如下表:
最後是d,計算類型選取器、偽類的個數,選取器中有三個:body、div、p,沒有偽類元素,所以d=3,如下表:
就此打住,讓我們來看一個更為複雜的例子,對於同一個元素有不止一個的color屬性,瀏覽器如何處理,下面是樣式單:複製內容到剪貼簿
代碼:
p.message{
color:green;
}
#home #warning p.message{
color:yellow;
}
#warning p.message{
color:white;
}
body#home div#warning p.message{
color:blue;
}
p{
color:teal;
}
* body#home>div#warning p.message{
color:red;
}
#warning p{
color:black;
}
用上面的方法來分析這個樣式單。稍等,通用選擇符“*”和子選擇符“>”的優先順序是怎樣的?答案是他沒有任何優先順序,在就算中將被忽略,你可以將其當作0來對待。
在不看下面的結果之前,你是否已經分析出了選取器的優先順序。
果是根據優先順序優先順序的高低來排列的:最高的在最上面,最低的屈居於下。你會看到,最上面的兩條層級相同,儘管它多了一個通用選擇符和子選擇符。在這種情況下,後來者將佔據上風,如果你在頁面中使用上面的樣式,你將會看到,p元素的文本字型將會使紅色。
你也會看到,p.message優先順序低於#waring p。這是初學者經常遇到的問題,他們認為類別選取器更具體的匹配一個元素。