在實際的工作中,我們可能還有些疑惑,當有多個選擇器作用在一個元素上時,哪個規則最終會應用到元素上?其實這是通過層疊機制來控制的,這也和樣式繼承(元素從其父元素那裡獲得屬性值)有關。
層疊
CSS 是 Cascading Style Sheets
的縮寫,這暗示 層疊(cascade)
的概念是很重要的。在最基本的層面上,它表明CSS規則的順序很重要,但它比那更復雜。什麼選擇器在層疊中勝出取決於三個因素(這些都是按重量級順序排列的——前面的的一種會否決後一種):
- 重要性(Importance)
- 特殊性(Specificity)
- 原始碼次序(Source order)
重要性
!important
在CSS中,有一個特別的語法可以讓一條規則總是優先於其他規則:!important。把它加在屬性值的後面可以使這條宣告有無比強大的力量。
注意: 過載這個 !important 宣告的唯一方法是在後面的原始碼或者是一個擁有更高特殊性的原始碼中包含相同的 !important 特性的宣告。
知道 !important存在是很有用的,這樣當你在別人的程式碼中遇到它時,你就知道它是什麼了。但是!我們建議你千萬不要使用它,除非你絕對必須使用它。您可能不得不使用它的一種情況是,當您在CMS中工作時,您不能編輯核心的CSS模組,並且您確實想要重寫一種不能以其他方式覆蓋的樣式。 但是,如果你能避免的話,不要使用它。由於 !important 改變了層疊正常工作的方式,因此除錯CSS問題,尤其是在大型樣式表中,會變得非常困難。
樣式表來源
要注意一個CSS宣告的重要性取決於它被指定在什麼樣式表內——使用者可以設定自定義樣式表覆蓋開發商的樣式,例如使用者可能有視力障礙,想設定字型大小對所有網頁的訪問是雙倍的正常大小,以便更容易閱讀。
相互衝突的宣告將按以下順序適用,後一種將覆蓋先前的宣告:
- 在使用者代理樣式表的宣告 (例如:瀏覽器在沒有其他宣告的預設樣式).
- 使用者樣式表中的普通宣告(由使用者設定的自定義樣式)。
- 作者樣式表中的普通宣告(這是我們設定的樣式,Web開發人員)。
- 作者樣式表中的重要宣告
- 使用者樣式表中的重要宣告(優先順序最高)
Web開發者的樣式表覆蓋使用者的樣式表是合理的,所以設計可以保持預期,但是有時候使用者有很好的理由來重寫web開發人員樣式,如上所述,這可以通過在使用者的規則中使用 !important
。
特殊性
特殊性基本上是衡量選擇器的具體程度的一種方法——它能匹配多少元素。如上面所示的示例所示,元素選擇器具有很低的特殊性。類選擇器具有更高特殊性,所以將戰勝元素選擇器。ID選擇器有甚至更高的專用性, 所以將戰勝類選擇器。
一個選擇器具有的專用性的量是用四種不同的值(或元件)來衡量的,它們可以被認為是千位,百位,十位和個位——在四個列中的四個簡單數字:
- 千位:如果宣告是在 style 屬性中該列加1分(這樣的宣告沒有選擇器,所以它們的專用性總是1000。)否則為0。
- 百位:在整個選擇器中每包含一個
ID選擇器就
在該列中加1分。 - 十位:在整個選擇器中每包含一個
類選擇器
、屬性選擇器
、或者偽類
就在該列中加1分。 - 個位:在整個選擇器中每包含一個
元素選擇器
或偽元素
就在該列中加1分。
注意: 通用選擇器 (*), 複合選擇器 (+, >, ~, ` `) 和否定偽類 (:not) 在專用性中無影響。
示例
選擇器 | 千位 | 百位 | 十位 | 個位 | 合計值 |
---|---|---|---|---|---|
h1 | 0 | 0 | 0 | 1 | 0001 |
#important | 0 | 1 | 0 | 0 | 0100 |
h1 + p::first-letter | 0 | 0 | 0 | 3 | 0003 |
li > a[href*=”zh-CN”] > .inline-warning | 0 | 0 | 2 | 2 | 0022 |
#important div > div > a:hover, 在一個元素的 <style> 屬性裡 |
1 | 1 | 1 | 3 | 1113 |
注意: 如果多個選擇器具有相同的重要性和專用性,則選擇哪一個選擇器取決於 Source order(原始碼次序)。
原始碼次序(Source order)
如果多個相互競爭的選擇器具有相同的重要性和專用性,那麼第三個因素將幫助決定哪一個規則獲勝——後面的規則將戰勝先前的規則。
繼承
CSS繼承是我們需要研究的最後一部分,以獲取所有資訊並瞭解什麼樣式應用於元素。其思想是,應用於某個元素的一些屬性值將由該元素的子元素繼承,而有些則不會。
哪些屬性預設被繼承哪些不被繼承大部分符合常識。如果你想確定,你可以 參考CSS參考資料—— 每個單獨的屬性頁都會從一個彙總表開始,其中包含有關該元素的各種詳細資訊,包括是否被繼承。
繼承屬性是CSS最基本的內容之一,一般不會特別考慮,但是還是要記住的是:
- 大部分框模型屬性(如border)不會繼承。
- 繼承沒有特殊性,且低於0,0,0,0 如 * {color: red;}
控制繼承
CSS為處理繼承提供了三種特殊的通用屬性值:
- inherit: 該值將應用到選定元素的屬性值設定為與其父元素一樣。
- initial :該值將應用到選定元素的屬性值設定為與瀏覽器預設樣式表中該元素設定的值一樣。如果瀏覽器預設樣式表中沒有設定值,並且該屬性是自然繼承的,那麼該屬性值就被設定為
inherit
。 - unset :該值將屬性重置為其自然值,即如果屬性是自然繼承的,那麼它就表現得像
inherit
,否則就是表現得像initial
。
總結
層疊樣式表這個名字很貼切。 CSS所採用的方法就是讓樣式層疊在一起,這是通過結合繼承和特殊性做到的•。CSS2.1 的層疊規則相當簡單。
- 找出所有相關的規則,這些規則都包含與一個給定元素匹配的選擇器。
- 按顯式權重對應用到該元素的所有宣告排序。標誌
!important
的規則的權重要高於沒有!important
標誌的規則。按來源對應用到給定元素的所有宣告排序。共有3種來源:創作人員、讀者和使用者代理。正常情況下,創作人員的樣式要勝過讀者的樣式。有!important
標誌的讀者樣式要強於所有其他樣式,這包括有!important
標誌的創作人員樣式。創作人員樣式和讀者樣式都比使用者代理的預設樣式要強。 - 按特殊性對應用到給定元素的所有宣告排序,有較高特殊性的元素權重大於有較低特殊性的元素.
- 按出現的序對應用到給定元素的所和宣告排序。一個宣告在樣式表或文件中越後出現,它的權重越大,如果樣式表中有匯入的樣式表,一般認為出現在匯入樣式表中的宣告在前,主樣式表中的所有宣告在後。
參考
- 《CSS 權威指南》
- MDN web docs