當你隨機打開一個頁面,查看源代碼,你會發現,同一個元素,不止有一個CSS選擇器及對應的樣式。而一個元素只能應用一個樣式,那么一堆樣式中究竟是應用哪一個呢?這就涉及到CSS的層疊規則了。下面就來總結下CSS的層疊規則。
概念:CSS中的層疊就是讓多個來源的樣式疊加在一起,然后結合樣式的特殊性(后面詳細介紹)、繼承性,確定最終應用的樣式。
樣式的來源分五種:
1、瀏覽器默認的樣式;
2、用戶自定義樣式。一些頁面中會提供一些讓用戶自定義字體大小顏色等的快捷鍵;
3、外部樣式,即<link>引用的CSS后綴文件;
4、內部樣式,即寫在<style></style>標簽內的樣式;
5、內聯樣式,即直接寫在style屬性內的樣式(現在的網頁設計強調結構、表現、行為三者分離,所以這個還是少用為好。我會強迫性移除內聯樣式的,哈哈);
CSS權威指南中對樣式來源的分類分成三種:
1、創作人員(上面提到的第3、4、5點都可歸到這一點)
2、讀者(用戶自定義樣式)
3、用戶代理(這個就是上面所說的瀏覽器默認樣式了)
來看一個例子:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <link rel="stylesheet" href="style.css" type="text/css"> 5 <style> 6 #p1 #p2{ 7 color:yellow; 8 } 9 .div1 .div2 #p1{ 10 color:green; 11 } 12 .div1 .div2 p{ 13 color:gray; 14 } 15 .div1 .div2 .impo{ 16 color:green; 17 } 18 .impo{ 19 color: brown !important; 20 } 21 </style> 22 </head> 23 <body> 24 <div class="div1"> 25 <div class="div2"> 26 <p id="p1">Hello world</p> 27 <p id="p2" style="color: red">Hello, how are you!</p> 28 <p class="impo">I'm important!</p> 29 </div> 30 </div> 31 </body> 32 </html> 33 34 Style.css文件的代碼: 35 .div1 .div2 #p1{ 36 color: blue; 37 }
這個例子中,這三行文字的顏色分別是什么呢?相信你們很多人也知道了。答案先不揭曉,繼續往下看。
CSS2.1層疊規則是:
1、找出所有相關的規則,這些規則都包含與一個給定元素匹配的選擇器。
2、按顯式權重對應用到該元素的所有聲明進行排序,有!important標志的聲明的權重要高於不帶!important標志的聲明。
3、按來源對應用到給定元素的所有聲明進行排序。正常情況下,創作人員的樣式要勝過讀者的樣式。有!important標志的的讀者樣式要強於所有其他樣式,包括有!important標志的創作人員樣式。創作人員的樣式和讀者樣式斗都比用戶代理的默認樣式強。
4、按特殊性對應用到給定元素的所有聲明進行排序,有較高特殊性的元素權重要大於有較低特殊性的元素。
5、按出現順序對應用到給定元素的所有聲明進行排序,后面出現的聲明權重要大於前面出現的聲明,即后定義的樣式會覆蓋前面定義的樣式。
簡單總結:找出一個給定元素的所有聲明后,先按顯式權重和來源進行排序。如果相同,則比較特殊性。若再相同,則比較順序。
根據以上的知識,我們很明確知道了上面的例子三行文字的顏色是什么了:
第一行是文字的顏色是green;第二行文字的顏色是red;第三行文字顏色是brown。
下面着重講解下選擇器的特殊性:
1、對於內聯樣式,特殊性首位加1,即1,0,0,0。
2、對於選擇器中出現的ID屬性值,加0,1,0,0, 有多少個ID值就在第二位加幾位。
3、對於選擇器中出現的類屬性值,屬性選擇及偽類,加0,0,1,0,共出現多少個就在第三位加幾位。
4、對於選擇器中出現的元素,以及偽元素,加0,0,0,1,共出現多少個就在第四位加幾位。
5、通配符對特殊性沒有任何貢獻,即特殊性是0,0,0,0。
6、結合符沒有特殊性,連0特殊性也沒有。
7、繼承的CSS完全沒有特殊性,連0特殊性也沒有(CSS中的繼承是有選擇性的,並不是全部CSS都繼承,像邊框屬性就不會繼承)。
注:偽元素選擇器包含以下幾種:
1、:first-line; 用於向文本的首行設置特殊樣式;
2、:first-letter; 用於向文本的首字母設置特殊樣式;
3、:before; 可以在元素的內容前面插入新內容;
4、:after; 可以在元素的內容之后插入新內容;
5、::selection 選擇被用戶選取的元素部分(CSS3中新加的選擇器);
下面再來看一個例子:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <style type="text/css"> 5 #content #main-content h2{ 6 color:red; 7 } 8 9 #content #main-content>h2{ 10 color:blue ; 11 } 12 body #content div[id="main-content"] h2{ 13 color:green; 14 } 15 16 #main-content div.paragraph h2{ 17 color:orange; 18 } 19 #main-content [class="paragraph"] h2{ 20 color:yellow; 21 } 22 div#main-content div.paragraph h2.first{ 23 color:pink; 24 25 } 26 </style> 27 28 </head> 29 <body> 30 <div id="content"> 31 <div id="main-content"> 32 <h2>學習HTML</h2> 33 <div class="paragraph"> 34 <h2 class="first">學習CSS</h2> 35 </div> 36 </div> 37 </div> 38 39 </body> 40 </html>
這兩個標題的顏色分別是什么呢?
用剛剛講的特殊性規則計算下這六個樣式的特殊性:
第一個規則特殊性的值是:0,2,0,1
第二個規則特殊性的值是:0,2,0,1
第三個規則特殊性的值是:0,1,1,3
第四個規則特殊性的值是:0,1,1,2
第五個規則特殊性的值是:0,1,1,1
第六個規則特殊性的值是:0,1,2,3
這樣很明確知道了,特殊性最高的是第一和第二條規則,但第二條規則在后面,所以第一個標題的顏色是blue,第二個標題的顏色是red.
在這里要重點提一下,0特殊性(通配符)和沒有特殊性(結合符和繼承)是有很大差別的,這種差別決不能忽視。
看下面的例子,就可以看出兩者的區別了:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <style type="text/css"> 5 *{ 6 color:gray; 7 } 8 h1#page-title{ 9 color:red; 10 } 11 </style> 12 </head> 13 <body> 14 <div> 15 <h1 id="page-title">Hello<em>world</em></h1> 16 </div> 17 </body> 18 </html>
這其中Meerkat的顏色是red,但Central的顏色是gray。因為通配符*的特殊性是0, 而繼承的CSS是沒有特殊性的,連0也沒有,所以,通配符的權重要大於繼承。
說了特殊性,這里也順便引入一遍文章,這是對特殊性的另一方面的說明。