CSS 選擇器效能優化

admin發表於2019-01-14

在從事前端之初,很可能,讓頁面能夠正常顯示就是最大的目的。

但是隨著技術進步,頁面的正常顯示已經不是最高追求,轉而追求更好的效能。

就如同解決溫飽之後,必然會追求生活品質,這不僅是專案本身的需求,也在於對自身提高的內在要求。

本文介紹如何使用CSS選擇器才能提升效能,對於小型專案可能無關緊要,但是對於龐大的專案則效果明顯。

一.CSS選擇器的解讀:

我們總是以自己固有的思維習慣去理解一些事物,從而導致一些誤讀。

對於瀏覽器如何解析CSS選擇器可能也會有類似的誤讀,以如下簡短程式碼為例子:

[CSS] 純文字檢視 複製程式碼
#ant > a{
  color: red;
  font-size: 12px;
}

非常簡單的一段程式碼,常見錯誤分析如下:

(1).首先,找到id屬性值為"ant"的元素。

(2).然後,再在上述元素中查詢連結<a>元素。

讀書絕大多數是從左到右,程式碼的解析大多也是如此,所以很有可能想當然認為,CSS選擇器的解讀也是從左到右,然而事實卻恰恰相反,是從右向左進行解析的,正確方式如下:

(1).首先,超找頁面中的所有連結<a>元素。

(2).然後,沿著DOM樹繼續向上超找連結<a>的直接父元素的id屬性值是否是"ant"。

對於CSS選擇器的解讀方式總結如下兩點:

(1).從右向左進行匹配。

(2).如果當前選擇器的左邊還有其他原則器,那麼會繼續向左匹配,直到超找到匹配的元素或者退出匹配。

二.CSS選擇器的效能:

不同型別的選擇器,效能可能會大相徑庭,比如類選擇器的效能就遠高於萬用字元選擇器(*)。

看如下簡單程式碼例項:

[CSS] 純文字檢視 複製程式碼
#ant * {
  color: red;
  font-size: 12px;
}

上述程式碼的效能非常差,尤其對於一個超大型頁面,由於從右向左進行匹配,這個萬用字元會匹配頁面所有的元素,這個開銷是非常大的,所以一個CSS選擇器效能的關鍵在於最.右側的選擇器,所以通常稱最右側的選擇器為“關鍵選擇器”,所以選擇器優化的最關鍵的一點就是“關鍵選擇器越具體,效能越好”。常見選擇器效能排序如下:

(1).ID選擇器

(2)類選擇器

(3)元素選擇器

(4)兄弟選擇器

(5)子選擇器

(6)後代選擇器

(7)屬性選擇器

(8)偽類/偽元素選擇器

上面是常見的CSS選擇器,效能從上到下越來越低。

特別說明:id可能確實比類效能要好,但是也好不到哪裡去,基本上屬於伯仲之間,差距沒有想象的那麼大。

三.CSS選擇器優化推薦:

瞭解到CSS選擇器的匹配順序,和單個選擇器之間的效能差距。

那麼就可以根據對應的規律,寫出效能更為良好的選擇器,下面列舉幾個常見的推薦:

(1).儘可能不使用萬用字元選擇器:

[CSS] 純文字檢視 複製程式碼
#ant * {
  color: red;
  font-size: 12px;
}

前面說過,關鍵選擇器越具體越好,萬用字元選擇器實在是最不具體的一個。

(2).合理避免使用id選擇器:

前面說過,id選擇器的效能最好,難道我們將每一個元素都新增一個id屬性,肯定不現實。不過規範還是建議儘可能少的使用id選擇器,這就是最佳實踐與最佳效能之間的一個平衡或者取捨。

使用id確定元素在網頁中的位置,應該始終考慮使用class,而不是id,除非只使用一次。

id選擇器用於標識持久的結構性元素,此元素並不能重複使用,比如一個導航模組:

[CSS] 純文字檢視 複製程式碼
#nav {
  color: red;
  font-size: 12px;
}

(3).避免使用標籤限定id或者類選擇器:

程式碼中經常看到如下幾種使用方式,簡單舉例如下:

[CSS] 純文字檢視 複製程式碼
div#nav {}
div.ant {}

尤其是不能理解第一個選擇器,id已經可以確定一個元素了,為何還要來一個標籤限制。

本來id選擇器檢索到指定元素了,發現左側還有一個div選擇器,還要耗費一下效能。

(3).減少後代選擇器的使用:

儘可能避免使用後代選擇器,最好使用子選擇器替代。

div>a的效能肯定要好於div a。

首先使用a選擇器匹配頁面所有連結<a>元素,後代選擇器要一層層查詢最終確定當前a是否具有div父元素,但是子元素選擇器只要查詢一層就可以了,效能可以優化很多。

(4).儘可能使用繼承:

[CSS] 純文字檢視 複製程式碼
#nav {} 
#nav > .span { font-size:24px; } 
#nav > .a { font-size:24px; }

上述程式碼可以優化如下:

[CSS] 純文字檢視 複製程式碼
#nav {font-size:24px;}

使用繼承,而不是每一個選擇器都設定一次。

相關文章