譯自:http://css-tricks.com/efficiently-rendering-css/
無可否認我並不經常考慮這個問題… 我們書寫的CSS的效率如何,瀏覽器渲染它的速度如何?
瀏覽器的開發者肯定關心這個問題(頁面加載越快,人們用着越開心)。Mozilla有篇文章 about best practices。Google同樣致力於讓web更快,他們也有篇文章article about it。
先來了解一下他們提出的主要想法,然后討論其實用性。
#從右至左#
弄明白瀏覽器是怎樣解讀CSS選擇器的重要一件事情是:瀏覽器按“從右向左”讀取。意味着在選擇器 ul > li a[title="home"] 中,首先被解析的是a[title="home"]。這第一部分也被稱為“目標選擇器”,最終選擇的元素是它。
#ID選擇符最高效,通配選擇符效率最低#
這里有四種目標選擇器:ID,class,tag和通配符。按照效率排列如下。
#main-navigation { } /* ID (最快) */
body.home #page-wrap { } /* ID */
.main-navigation { } /* Class */
ul li a.current { } /* Class *
ul { } /* Tag */
ul li a { } /* Tag */
* { } /* 通配 (最慢) */
#content [title='home'] /* 通配 */
結合“從右至左”和目標選擇器的思想,可以看出這樣的選擇器效率不是很高:
#main-nav > li { } /* 比你想象的要慢 */
即使這讓人感到有悖常理…因為ID最有效,所以我們認為瀏覽器會快速地找到ID,然后很快地找到li子元素。但實際上,最先運行的是相對低效的li元素選擇器。
#不要用標簽修飾#
千萬別這樣做:
ul#main-navigation { }
ID是唯一的,所以它們不需要和標簽在一起。這樣做反而會降低效率。如果可以避免的話,也不要用class修飾。class不唯一,所以理論上你可以對多個不同的元素應用一個class。如果想讓標簽控制樣式,你可能會加以標簽修飾(eg:li.first),但這種做法很罕見,所以還是別這樣做。
#后代選擇器是最糟糕的#
David Hyatt:
后代選擇器在CSS中是最昂貴的選擇器。貴得要命——尤其是把它和標簽或通配符放在一起!
換言之,像下面這樣的選擇器簡直是效率的災難:
html body ul li a { }
#一個選擇器匹配失敗比它被找到更高效#
我不確定這能讓我們學到很多,因為如果在你的CSS中有大量的選擇器未曾匹配任何東西…這太古怪了。不過也挺有趣,“從右至左”的解釋一個選擇器,一旦匹配失敗就停下來,相比繼續解釋下來所用精力更少。
#想想你為什么會寫出這樣的選擇器#
看看這個:
#main-navigation li a { font-family: Georgia, Serif; }
字體樣式,你可能不需要特意從一個選擇器(a標簽)開始(如果你只想換個字體)。這樣可能達到同樣的效果,但更加高效:
#main-navigation { font-family: Georgia, Serif; }
#CSS3和效率#
來自David Hyatt的噩耗:
關於CSS3選擇器的可悲的事實是,如果你關心頁面性能的話,他們真不該被使用!
整個評論是值得一讀的。
CSS3選擇器(例如:第n個孩子)是令人難以置信的好,在幫助我們鎖定我們想要的元素的同時保持標記的干凈和語義化,但事實是,這些花哨的選擇器讓更多的瀏覽器資源被密集使用。
到底怎么回事,我不應該使用它們嗎?讓我們想點實用性吧!
#實用性#
開頭提到Mozilla的文章?已經有10年了。事實上,10年前的計算機更慢。這些東西在那時候更重要。10年前我剛要21歲,根本不知道CSS是什么,所以沒法帶你去那些古老的學校…但我感覺,我們之所以不關心渲染效率的問題,是因為它從來都不是個大問題。
這是我的想法:上面提到的最佳實踐都是有意義的。你可以遵循,它們不會限制你的CSS能力。但你也不必太教條。如果你剛好需要改進從前的網站,又剛好沒有考慮過這些想法,不妨看看你的樣式表,哪里可以做得更好。如果你的網站沒有渲染速度的問題,不用去擔心,以后注意就可以了。
現在我們知道ID是最高效地選擇器。如果你想使頁面渲染最高效,你可以給每一個元素加上唯一的ID,然后對每個ID選擇器應用樣式。這超級快,同樣超級荒謬。這樣的頁面會極端的沒有語義,並且很難維護。即使在以表現為主的網站,也不會這樣做。我想,這堂課並不是為了高效的CSS而犧牲語義和可維護性。
感謝Jason Beaudoin email給我想法。如果有誰知道這個東西,或者你有額外的提示,請告訴我!
只是作為一個速記,我想提一提,因為CSS樣式選擇器也在許多JavaScript庫中使用,這些相同的概念也同樣適用。 ID選擇將是最快的,而復雜的后代選擇等會慢一些。