前端雜談: CSS 權重 (Specificity)

css 權重想必你們都據說過, 一些簡單的規則大部分人也都知道:css

  • 較長的 css selector 權重會大於較短的 css selectorhtml

  • id selector 權重高於 class selector.前端

可是具體規範是什麼? 瀏覽器是按照什麼標準來斷定不一樣選擇器的權重的呢?git

讓咱們來看一下官方文檔是怎麼說的~github

第一個關鍵詞: Specificity

Specificity is the means by which browsers decide which CSS property values are the most relevant to an element and, therefore, will be applied. Specificity is based on the matching rules which are composed of different sorts of CSS selectors瀏覽器

官方文檔中用 Specificity: 特異性 來表示一個 css selector 和其元素的相關性. 相關性越強, 即表示表示其權重最高.app

那麼問題來了, Specificity 是如何被比較的呢?

Specificity is a weight that is applied to a given CSS declaration, determined by the number of each selector type in the matching selector.ide

Specificity 是由 selector 中 不一樣 selector type 的數目決定的.post

第二個關鍵詞: Selector Type

根據 W3 標準中的規定, css selector 分爲 4 種 type: a, b, c, d. 他們的數目計算規則爲:測試

  • a: 若是 css 屬性聲明是寫在 style=「」 中的, 則數目爲 1, 不然爲 0
  • b: id 選擇器的數目
  • c: class 選擇器, 屬性選擇器(如 type=「text」), 僞類選擇器(如: ::hover) 的數目
  • d: 標籤名(如: p, div), 僞類 (如: :before)的數目

在比較不一樣 css selector 的權重時, 按照 a => b => c => d 的順序進行比較.

由第一個 selector type a 的計算規則可知: 寫在 html 代碼 style 屬性中的 css 相較寫在 css 選擇器中的 css 屬性具備最高的優先級.

而 id selector (b) 相較 class selector (c) 有更高的優先級. 這也和咱們平時的經驗相吻合.

還有一些 css 選擇器你沒提, 它們該怎麼計算權重?

除了上面 Specificity 計算規則中的 css 選擇器類型, 還有一些選擇器如: *, +, >,:not() 等. 這些選擇器該如何計算其權重呢?

答案是這些選擇器並不會被計算到 css 的權重當中 :)

有一個須要特別注意一下的選擇器: :not(), 雖然它自己是不計權重的, 可是寫在它裏面的 css selector 是須要計算權重的.

若是 a,b,c,d 算完都同樣, 怎麼辦?

默認行爲是: 當 specificity 同樣時, 最後聲明的 css selector 會生效.

若是我重複一樣的 css selectory type, 權重會增長嗎?

讓咱們來作個實驗, 咱們聲明一個 html 節點:

<div>
  <div id="testId" class="testClass"><span>test div</span></div>
</div>
複製代碼

在 css 中咱們添加兩個選擇器:

.testClass.testClass {
  background-color: red;
}
.testClass {
  background-color: black;
}
複製代碼

若是重複的 css selector 會被忽略的話, 按照前面的規則, 最後聲明的 css selector 會生效, 因此 這個 div 節點背景色應該是黑色. 讓咱們看看結果:

FSvsHI.png

結果咱們獲得的是一個紅色的 div, 也就是說 .testClass.testClass 高於 .testClass. 因此結論是: 重複的 css selector, 其權重會被重複計算.

關於 !important:

按照 MDN的說法, !important 是不在 css 選擇器的權重計算範圍內的, 而它之因此能讓 css 選擇器生效是由於瀏覽器在碰見 !important 時會進行特殊的判斷. 當多個 !important 須要進行比較時, 纔會計算其權重再進行比較.

一般來講, 不提倡使用 !important. 若是你認爲必定要使用, 不妨先自檢一下:

  • 老是先考慮使用權重更高的 css 選擇器, 而不是使用 !important
  • 只有當你的目的是覆蓋來自第三方的 css(如: Bootstrap, normalize.css)時, 纔在頁面範圍使用 !important
  • 永遠不要 在你寫一個第三方插件時使用 !important
  • 永遠不要在全站範圍使用 !important

一些誤導的信息

我在搜索關於 css 權重的資料時, 看到了下面這張圖, 看似十分有道理, 但實際上是錯誤的!

css_weight1

讓咱們來作一個簡單的測試:

按照圖片中的計算公式: 若是一個 css 選擇器包含11 個 class selector type, 另外一個選擇器是1 個 id selector type. 那麼 class 選擇器的權重會高於 id 選擇器的權重. 讓咱們來試一試:

.testClass.testClass.testClass.testClass.testClass.testClass
  .testClass.testClass.testClass.testClass.testClass {
  background-color: red;
}
#testId {
  background-color: black;
}
複製代碼

讓咱們看看結果:

FSvfgg.png

結果顯示仍是 id 選擇器權重更高.

雖然咱們在實際編碼過程當中不多會出現 10 多個 class 的狀況, 但萬一出現了, 知道權重真正的計算比較規則, 咱們才能正確的處理~

想了解更多 前端 和 數據可視化 ?

這裏是個人 D3.js數據可視化 的 github 地址, 歡迎 star & fork :tada:

D3-blog

若是以爲本文不錯的話, 不妨點擊下面的連接關注一下 : )

github 主頁

知乎專欄

掘金

想直接聯繫我 ?

郵箱: ssthouse@163.com

歡迎關注個人公衆號:

相關文章
相關標籤/搜索