- HTML5權威指南
- (美)Adam Freeman
- 3242字
- 2020-01-10 15:29:15
4.2 樣式的層疊和繼承
要想掌握樣式表,弄清樣式層疊和繼承這兩個概念是關鍵。瀏覽器根據層疊和繼承規則確定顯示一個元素時各種樣式屬性采用的值。每個元素都有一套瀏覽器呈現頁面時要用到的CSS屬性。對于每一個這種屬性,瀏覽器都需要查看一下其所有的樣式來源。前面已經講過三種定義樣式的方式(元素內嵌、文檔內嵌和外部樣式表),但是要知道,樣式還有另外兩個來源。
4.2.1 瀏覽器樣式
瀏覽器樣式(更恰當的名稱是用戶代理樣式)是元素尚未設置樣式時瀏覽器應用在它身上的默認樣式。這些樣式因瀏覽器而略有差異,不過大體一致。以a元素(超鏈接)為例,想想沒有特別為它定義樣式時瀏覽器會怎樣顯示。代碼清單4-10所示為一個不含任何樣式的簡單HTML文檔。
代碼清單4-10 不含樣式的HTML文檔
<! DOCTYPE HTML> <html> <head> <title>Example</title> </head> <body> <a >Visit the Apress website</a> <p>I like <span>apples</span> and oranges.</p> <a >Visit the W3C website</a> </body> </html>
該例只是在前面例子的基礎上做了一點改動,去掉了所有樣式。從圖4-7中可以看到瀏覽器是如何顯示a元素的。

圖4-7 超鏈接元素的默認樣式
我們對瀏覽器應用于鏈接的樣式早已習以為常,以至于不會留意到它的存在。但是只要駐目細看,樣式的細節就會浮現出來。鏈接的文字內容被顯示為藍色,而且帶有下劃線。據此推測,瀏覽器相當于應用了類似代碼清單4-11所示的樣式。
代碼清單4-11 推測出來的a元素的默認瀏覽器樣式
a { color: blue; text-decoration: underline; }
雖然不是每一個HTML元素都有默認的瀏覽器樣式,但是多數元素都有。本書介紹HTML元素的各章都會介紹常見瀏覽器一般都會應用的典型默認樣式。關于a元素的介紹參見第8章。
4.2.2 用戶樣式
大多數瀏覽器都允許用戶定義自己的樣式表。這類樣式表中包含的樣式稱為用戶樣式。這個功能用的人不多,不過,那些要定義自己的樣式表的人往往比較看重這一點,一個特別的原因是這可以讓有生理不便的人更容易使用網頁。
各種瀏覽器都有自己管理用戶樣式的方式。以谷歌的Chrome為例,它會在用戶的個人配置信息目錄中生成一個名為Default\User StyleSheets\Custom.css的文件。添加到這個文件中的任何樣式都會被用于用戶訪問的所有網站,只不過要依下節所講的層疊規則行事。代碼清單4-12所示簡例展示了我在自己的Custom.css文件中加入的一條樣式。
代碼清單4-12 在用戶樣式表中添加樣式
a { color: white; background:grey; text-decoration: none; padding: 2px; }
這條樣式的作用對象是a元素,它蓋過了默認的瀏覽器樣式。圖4-8顯示了重新載入代碼清單4-10中的HTML文檔后上述用戶樣式的效果。

圖4-8 定義用戶樣式
4.2.3 樣式如何層疊
明白了瀏覽器所要查看的所有樣式來源之后,現在可以看看瀏覽器要顯示元素時求索一個CSS屬性值的次序。這個次序很明確:
(1)元素內嵌樣式(用元素的全局屬性style定義的樣式);
(2)文檔內嵌樣式(定義在style元素中的樣式);
(3)外部樣式(用link元素導入的樣式);
(4)用戶樣式(用戶定義的樣式);
(5)瀏覽器樣式(瀏覽器應用的默認樣式)。
設想用戶需要顯示一個a元素。瀏覽器需要知道的一件事情是其文字應顯示為哪種顏色。為了解決這個問題,它需要為CSS屬性color找到一個值。首先它會查看所要呈現的那個元素是否具有一條設定了color值的元素內嵌樣式。比如下面這種:
<astyle="color:red">Visit the Apress website</a>
如果不存在元素內嵌樣式,那么接下來瀏覽器會看看是否有一個style元素包含著作用于那個元素的樣式。比如下面這種:
<style type="text/css">
a {
color: red;
}
</style>
如果不存在這樣的style元素,那么瀏覽器接下來會查看用link元素載入的樣式表。依次類推,直到找到一個color屬性值或查完用戶定義樣式。在后面一種情況下,最終使用的將是瀏覽器默認樣式中的值。
前述次序表中的前三個屬性來源(元素內嵌樣式、文檔內嵌樣式和外部樣式表)合稱作者樣式。定義在用戶樣式表中的樣式稱為用戶樣式。由瀏覽器定義的樣式則稱為瀏覽器樣式。
4.2.4 用重要樣式調整層疊次序
把樣式屬性值標記為重要(important),可以改變正常的層疊次序,如代碼清單4-13所示。
代碼清單4-13 將樣式屬性標記為重要
<! DOCTYPE HTML> <html> <head> <title>Example</title> <style type="text/css"> a { color: black !important; } </style> </head> <body> <astyle="color:red">Visit the Apress website</a> <p>I like <span>apples</span> and oranges.</p> <a >Visit the W3C website</a> </body> </html>
在樣式聲明后附上!important即可將對應屬性值標記為重要。不管這種樣式屬性定義在什么地方,瀏覽器都會給予優先考慮。從圖4-9中可以看到重要屬性的效果(印刷頁面上看起來可能不太清楚)。此例中文檔內嵌樣式的color屬性值蓋過了元素內嵌樣式中的值。

圖4-9 重要屬性值蓋過元素內嵌樣式屬性值
提示
能凌駕于作者定義的重要屬性值之上的只有用戶樣式表中定義的重要屬性值。對于普通屬性,作者樣式中的值優先于用戶樣式中的值,而對于重要屬性情況正好相反。
4.2.5 根據具體程度和定義次序解決同級樣式沖突
如果有兩條定義于同一層次的樣式都能應用于同一個元素,而且它們都包含著瀏覽器要查看的CSS屬性值,這時就需要另加砝碼助天平上持平的雙方一決高下。為了判斷該用哪個值,瀏覽器會評估兩條樣式的具體程度,然后選中較為特殊的那條。樣式的具體程度通過統計三類特征得出:
(1)樣式的選擇器中id值的數目;
(2)選擇器中其他屬性和偽類的數目;
(3)選擇器中元素名和偽元素的數目。
第17章和第18章將會說明如何編寫包含所有這些特征的選擇器。瀏覽器將三類評估所得值結合起來,由此辨識出最特殊的樣式并采用其屬性值。代碼清單4-14是有關具體程度的一個非常簡單的例子。
代碼清單4-14 樣式的具體程度
<! DOCTYPE HTML> <html> <head> <title>Example</title> <style type="text/css"> a { color: black; } a.myclass { color:white; background:grey; } </style> </head> <body> <a >Visit the Apress website</a> <p>I like <span>apples</span> and oranges.</p> <a class="myclass" >Visit the W3C website</a> </body> </html>
在評定具體程度時要按a-b-c的形式(其中每一個字母依次代表上述三類特征的統計結果)生成一個數字。它不是一個三位數。如果對某個樣式算出的a值最大,那么它就是具體程度高的那個。只有a值相等時瀏覽器才會比較b值,此時b值較大的樣式具體程度更高。只有a值和b值都分別相等時瀏覽器才會考慮c值。也就是說,1-0-0這個得分比0-5-5這個得分代表的具體程度更高。
本例中a.myclass這個選擇器含有一個class屬性,于是該樣式的值為0-1-0(0個id值+1個其他屬性+0個元素名)。另一條樣式的具體程度值為0-0-0(因為它不包含id值、其他屬性或元素名)。因此瀏覽器在呈現被歸入myclass類的a元素時將使用a.myclass樣式中設定的color屬性值。對于所有其他a元素,使用的則是另一條樣式中設定的值。從圖4-10可以看出在本例中瀏覽器是如何選擇和應用樣式的。

圖4-10 根據具體程度選用樣式屬性值
如果同一個樣式屬性出現在具體程度相當的幾條樣式中,那么瀏覽器會根據其位置的先后選擇所用的值,規則是后來者居上。代碼清單4-15所示例子就包含了兩條具體程度相同的樣式。
代碼清單4-15 具體程度相同的樣式
<! DOCTYPE HTML> <html> <head> <title>Example</title> <style type="text/css"> a.myclass1 { color: black; } a.myclass2 { color:white; background:grey; } </style> </head> <body> <a >Visit the Apress website</a> <p>I like <span>apples</span> and oranges.</p> <a class="myclass1 myclass2" >Visit the W3C website</a> </body> </html>
此例style元素中定義的兩條樣式在具體程度上得分相同。瀏覽器在呈現頁面上的第二個a元素時,為樣式屬性color選用的值是white,這是因為該值來自靠后的那條樣式。其結果如圖4-11所示。

圖4-11 根據樣式定義的先后選擇屬性值
為了證實瀏覽器是用這個方法選擇所用的color屬性值,代碼清單4-16中的例子顛倒了兩條樣式的位置。
代碼清單4-16 顛倒樣式定義的次序
<! DOCTYPE HTML> <html> <head> <title>Example</title> <style type="text/css"> a.myclass2 { color:white; background:grey; } a.myclass1 { color: black; } </style> </head> <body> <a >Visit the Apress website</a> <p>I like <span>apples</span> and oranges.</p> <a class="myclass1 myclass2" >Visit the W3C website</a> </body> </html>
不出所料,現在瀏覽器為color屬性選擇的是black這個值,如圖4-12所示。

圖4-12 改變樣式定義次序的效果
根據樣式的具體程度和定義次序確定選用的樣式屬性值,應該把各個屬性分開考慮。本節的幾個例子還定義了背景顏色屬性的值。因為該值并非兩個樣式中都有,所以不會發生沖突,也就沒有必要查找其他值。
4.2.6 繼承
如果瀏覽器在直接相關的樣式中找不到某個屬性的值,就會求助于繼承機制,使用父元素的這個樣式屬性值。如代碼清單4-17所示。
代碼清單4-17 CSS屬性繼承
<! DOCTYPE HTML> <html> <head> <title>Example</title> <style type="text/css"> p { color:white; background:grey; border: medium solid black; } </style> </head> <body> <a >Visit the Apress website</a> <p>I like <span>apples</span> and oranges.</p> <a class="myclass1 myclass2" >Visit the W3C website</a> </body> </html>
本例關注的是瀏覽器應用于span元素(其父元素為p)的樣式。圖4-13是這個文檔在瀏覽器中的顯示效果。

圖4-13 使用繼承的CSS屬性值
這個文檔并沒有在針對span元素的樣式中設定color屬性值,但是瀏覽器顯示該元素的文字內容時卻使用了前景色white。這個值系由父元素p繼承而來。
令人撓頭的是,并非所有CSS屬性均可繼承。這方面有條經驗可供參考:與元素外觀(文字顏色、字體等)相關的樣式會被繼承;與元素在頁面上的布局相關的樣式不會被繼承。在樣式中使用inherit這個特別設立的值可以強行實施繼承,明確指示瀏覽器在該屬性上使用父元素樣式中的值。代碼清單4-18示范了inherit的用法。
代碼清單4-18 使用inherit
<! DOCTYPE HTML> <html> <head> <title>Example</title> <style type="text/css"> p { color:white; background:grey; border: medium solid black; } span { border: inherit; } </style> </head> <body> <a >Visit the Apress website</a> <p>I like <span>apples</span> and oranges.</p> <a class="myclass1 myclass2" >Visit the W3C website</a> </body> </html>
此例定義了一條用于span元素的樣式,其border屬性值繼承自父元素。文檔的顯示效果見圖4-14。現在span元素和包含它的p元素均具有邊框。

圖4-14 使用inherit