CSS選擇器效率問題

今天學習了CSS各種選擇器,對其效率問題有些疑問,故總結了一些學習筆記php

有不少人都忘記了,或在簡單的說沒有意識到,CSS在咱們手中,既能很高效,也能夠變得很低能。這很容易被忘記,尤爲是當你意識到你會的太少,CSS代碼效率很低的時候。css

下面的規則只真正被應用到那些速度要求很高,有成百上千的DOM元素被繪製在頁面上的大型網站。可是,實踐出真理,這和你是在建立下一個Facebook,仍是寫一個本地的展現頁面都沒有關係,多知道一點老是好的。html

CSS選擇器:

對咱們大多數人來講,CSS選擇器並不陌生。最基本的選擇器是元素選擇器(好比div),ID選擇器(好比#header)還有類選擇器(好比.tweet)。web

一些的不常見的選擇器包括僞類選擇器(:hover),不少複雜的CSS3和正則選擇器,好比:first-child,class ^= 「grid-」.瀏覽器

CSS選擇器具備高效的繼承性,引用Steve Souders的話, CSS選擇器效率從高到低的排序以下:app

  1. ID選擇器 好比#header
  2. 類選擇器 好比.promo
  3. 元素選擇器 好比 div
  4. 兄弟選擇器 好比 h2 + p
  5. 子選擇器 好比 li > ul
  6. 後代選擇器 好比 ul a 7. 通用選擇器 好比 *
  7. 屬性選擇器 好比 type = 「text」
  8. 僞類/僞元素選擇器 好比 a:hover

以上引用自Steve Souders的Even Faster網站、性能

咱們不得不提的是,縱使ID選擇器很快、高效,可是它也僅僅如此。從Steve Souders的CSS Test咱們能夠看出ID選擇器類選擇器在速度上的差別很小很小。學習

在Windows系統上的Firefox 6上,我測得了一個簡單類選擇器的(reflow figure)重繪速度爲10.9ms,而ID選擇器爲12.5ms,因此事實上ID比類選擇器重繪要慢一點點。測試

ID選擇器和類選擇器在速度上的差別基本上沒有關係。網站

在一個標籤選擇器(a)的測試上顯示,它比類或ID選擇器的速度慢了不少。在一個嵌套很深的後代選擇器的測試上,顯示數據爲440左右!從這裏咱們能夠看出ID/類選擇器 和 元素/後代選擇器中間的差別較大,可是相互之間的差別較小。

注意: 這些數據可能在不一樣計算機和瀏覽器中間的差別較大。強烈地建議你們在本身的機子上測試一下。

組合選擇器

你能夠有一個標準的選擇器好比 #nav,來選擇任何帶有ID爲」nav」的元素,或在你能夠有一個組合選擇器好比#nav a,來選擇任何在ID爲’nav’的元素裏面的連接元素

此刻,咱們讀這些是從左到右的方式。咱們是先找到#nav,而後從它的裏面找其餘元素。可是瀏覽器解析這些不是這樣的:瀏覽器解析選擇器是從右到左的方式。

在咱們看來,#nav裏面帶了一個a,瀏覽器倒是看到的a在#nav裏面。這些細微的差別對選擇器的效率有很大的影響,同時學這些差別也是頗有價值的。

若是想要知道更多瀏覽器這樣解析的緣由,請看Stack Overflow上的討論

瀏覽器從最右邊的元素開始(它想要渲染的元素),而後用它的方式回溯DOM樹比從DOM樹的最高層開始選擇向下尋找,甚至可能達不到最右邊的選擇器—關鍵的選擇器要高效。

這些對CSS選擇器的效率有很大的影響。

關鍵選擇器

關鍵選擇器,正如前面討論的同樣,是一個複雜的CSS選擇器中最右邊部分。它是瀏覽器最早尋找的。

如今咱們回到討論開始的地方,哪類選擇器是最高效的?哪一個是會影響選擇器效率的關鍵選擇器;寫CSS代碼的時候,關鍵選擇器是可否高效的決定因素。 一個關鍵CSS選擇器像這樣:

1
#content .intro {..}

是否是高效選擇器好比類選擇器天生就高效?瀏覽器會尋找.intro的實例(可能會不少),而後沿着DOM樹向上查找,肯定剛纔找到的實例是否在一個帶有ID爲」content」的容器裏面。

可是,下面的選擇器就表現的不是那麼好了:

1
#content * {..}

這個選擇器所作的是選擇全部在頁面上的單個元素(是每一個單個的元素),而後去看看它們是否有一個 #content 的父元素。這是一個很是不高效選擇器由於它的關鍵選擇器執行開銷太大了。

運用這些知識咱們就能夠在分類和選擇元素的時候作出更好的選擇。

假設你有一個複雜的頁面,它至關巨大而且在你的一個很大很大的站點上。在那個頁面上有成百上千甚至上萬的 a 標籤。它還有一個小的社交連接區域放在一個ID爲#social的Ul裏面。咱們假設它們是Twitter,Facebook,Dribbble還有 Google+的連接吧。在這個頁面上咱們有四個社交連接和成百上千的其餘連接。 下面的這個選擇器就天然的不是那麼高效和合理了:

1
#social a {…}

這裏發生的狀況是瀏覽器會在定位到#social區域下的四個連接以前獲得頁面上全部成千上萬的連接。咱們的關鍵選擇器匹配了太多咱們不感興趣的其餘元素。

爲了補救咱們能夠給每一個在社交連接區域的 a 增長一個更特殊、明確的選擇器 .social-link , 可是這好像有點違背咱們的認知:當咱們能用組合選擇器的時候就不要放沒必要要的類標示在元素上。

這就是爲何我對選擇器的性能如此感興趣的緣由了:必須在web 標準最佳實踐和速度之間的保持平衡。

一般咱們有:

1
2
3
4
5
6
<ul id= "social" >
     <li><a href= "#" class= "twitter" >Twitter</a></li>
     <li><a href= "#" class= "facebook" >Facebook</a></li>
     <li><a href= "#" class= "dribble" >Dribbble</a></li>
     <li><a href= "#" class= "gplus" >Google+</a></li>
</ul>

CSS:

1
#social a {}

咱們如今最好有:

1
2
3
4
5
6
< ul id = "social" >
     < li >< a href = "#" class = "social-link twitter" >Twitter</ a ></ li >
     < li >< a href = "#" class = "social-link facebook" >Facebook</ a ></ li >
     < li >< a href = "#" class = "social-link dribble" >Dribbble</ a ></ li >
     < li >< a href = "#" class = "social-link gplus" >Google+</ a ></ li >
</ ul >

加上CSS:

1
#social .social-link {}

這個新的關鍵選擇器將會匹配更少的元素,這意味着瀏覽器可以很快的找到它們並渲染特定的樣式,而後專一於下一件事。

另外,事實上咱們能夠用.social-link{}更清晰的選擇,而不是過度限制它。閱讀下一部分你會緣由…

簡單的重述一次,你的關鍵選擇器會決定瀏覽器的工做量,所以,咱們應該重視一下關鍵選擇器

過分限制選擇器

如今咱們知道了什麼是關鍵選擇器,還有它是大部分工做的來源,可是咱們能夠更樂觀一點。擁有一個明確的關鍵選擇器最大的好處就是你能夠避免使用過分限制選擇器。一個過分限制選擇器可能像:

1
html body .wrapper #content a {}

這裏的寫的太多了,至少3個選擇器是徹底不須要的。它能夠最多像這個樣子:

1
#content a {}

這會發生什麼呢? 首先第一個意味着瀏覽器不得不尋找全部的 a 元素,而後檢查他們是否在一個ID爲」content」的元素中,而後如此循環直到HTML標籤。這樣形成了太多的咱們不太想要的花費。瞭解了這個,咱們獲得一些更現實的例子:

1
#nav li a{}

變成這個:

1
#nav a {}

咱們知道若是a在li裏面,它也一定在#nav裏面,全部咱們能夠立刻把li從選擇器組中拿掉。而後,既然咱們知道在頁面中只有一個ID爲nav的元素,那麼它依附的元素就是徹底沒有關係得了,咱們也能夠拿掉ul

過分限制選擇器使瀏覽器工做比它實際須要的更繁重,花費的時間更多。咱們能夠刪掉沒必要需的限制,來使咱們的選擇器更簡單和高效。

這些真的須要嗎?

最短的答案是:或許不是。

最長的答案是:它取決於你正在搭建的站點。若是你正在爲你的晉升而努力,那麼就好好寫出簡單、高效的CSS代碼吧,由於你可能不會感受到它給你帶來的改變。 若是你正在搭建下一個每一個頁面都以毫秒計算的Amazon網站,這樣有時速度會很快,但有時可能不是。

瀏覽器將會在解析CSS的速度上變得更好,甚至在手機端。在一個網站上,你不太可能會覺察到一個低效的CSS選擇器,可是….

可是

它確實發生了,瀏覽器仍是不得不去作咱們討論的全部工做,不管它們變得多快。即便你不須要或者甚至不想實踐任何一個,可是它都是咱們值得學習的知識。請記住選擇器可能會讓你付出很大代價,你應該避免盯着一個看。這意味着若是你發現你本身在寫像這樣的:

1
div:nth-of-type( 3 ) ul:last-child li:nth-of-type(odd) *{ font-weight : bold }

這時,你可能就作錯了。

如今,在高效選擇器的世界我仍是一個新人。因此若是我忘記了什麼,或者你有須要補充的,請在評論裏面留言。

更多高效選擇器

我還不能徹底介紹Steve Souders的網站和書籍(《更快速網站》、《高性能網站》),它們是如此之好,以致於值得你花更多時間來閱讀和推薦。這個傢伙只有他本身才瞭解本身!

 

 

英文原文:Writing efficient CSS selectors,編譯:@freestyle21 和@沈濤-WEB工程師

譯文連接:http://blog.jobbole.com/35339/

相關文章
相關標籤/搜索