深入瀏覽器核心 高效CSS的秘訣
我們寫(xiě)的CSS有多高效?換個(gè)說(shuō)法,瀏覽器渲染我們的CSS會(huì)有多快?我承認(rèn)這個(gè)問(wèn)題我考慮的不夠多。這個(gè)問(wèn)題本應(yīng)該是瀏覽器廠商考慮的——他們的瀏覽器越快,用戶(hù)就越喜歡用他們的產(chǎn)品。
Mozilla有一篇關(guān)于這方面最佳實(shí)踐的文章,一直堅(jiān)持Web應(yīng)該更快的,我們一起看看他們闡釋的一些主要觀點(diǎn)。
從右向左
瀏覽器如何讀取你的CSS選擇器?如何巧妙的運(yùn)用CSS選擇器?我們需要明白的最重要的一點(diǎn)是從右向左。比如這個(gè)選擇器ul > li a[title="home"],瀏覽器首先讀取的是a[title="home"]。這個(gè)首先被讀取的部分我們叫它key selector,它是瀏覽器最終要選擇的元素。
ID最快,Universal最慢
有四種類(lèi)型的key selector,解析速度由快到慢依次是:ID、class、tag和universal:
- #main-navigation { } /* ID(最快) */
- body.home #page-wrap { } /* ID */
- .main-navigation { } /* Class */
- ul li a.current { } /* Class *
- ul { } /* Tag */
- ul li a { } /* Tag */
- * { } /* Universal(慢) */
- #content [title='home'] /* Universal */
我們把這個(gè)原則與從右向左結(jié)合來(lái)看,就會(huì)發(fā)現(xiàn)下面這個(gè)選擇器并不是很快:
- #main-nav > li { } /* 比它看起來(lái)的要慢 */
這真有點(diǎn)違反我們的直覺(jué),由于ID很快,我們直覺(jué)的以為瀏覽器會(huì)迅速的找到#main-nav,然后找到它的孩子。但實(shí)際上,瀏覽器首先解析的是相對(duì)較慢的。
不要tag-qualify
永遠(yuǎn)不要這樣做:
- ul#main-navigation { }
ID已經(jīng)是唯一的,不需要Tag來(lái)標(biāo)識(shí),這樣做會(huì)讓選擇器變慢。如果你可以,也盡量不要在class上這樣用。class不是唯一的,你可以用它來(lái)處理很多不同的元素。如果你希望擁有同一個(gè)class的元素有不同的樣式,你可能需要tag-qualify(比如li.first),但這是很少見(jiàn)的。
后代選擇器最糟糕
David Hyatt這樣說(shuō)過(guò):
The descendant selector is the most expensive selector in CSS. It is dreadfully expensive — especially if the selector is in the Tag or Universal Category.
換句話說(shuō),下面這個(gè)選擇器是很低效的:
- html body ul li a { }
匹配失敗的選擇器更高效
我不清楚從這里面我們可以學(xué)到什么,在自己的CSS文件里寫(xiě)很多沒(méi)用的東西豈不是很奇怪。但還是應(yīng)該說(shuō)明一下,當(dāng)從右向左的解析一個(gè)選擇器時(shí),如果沒(méi)有匹配的結(jié)果,瀏覽器將會(huì)停止下一步的動(dòng)作,于是更高效了。
想清楚你為什么這樣寫(xiě)
考慮這樣一個(gè)選擇器:
- #main-navigation li a { font-family: Georgia, Serif; }
font-family是可以級(jí)聯(lián)的,所以你可能根本不需要如此特殊的一個(gè)選擇器(如果你只是要改變字體的話)。這樣做會(huì)更高效,而且是高效很多:
- #main-navigation { font-family: Georgia, Serif; }
CSS 3的效率問(wèn)題
David Hyatt的說(shuō)法是,“關(guān)于CSS 3選擇器最可悲的是,他們不應(yīng)該將其只用在他們所關(guān)心的頁(yè)面性能上。”
CSS3選擇器(比如 :nth-child)能夠漂亮的定位我們想要的元素,又能保證我們的CSS整潔易讀。但是這些神奇的選擇器會(huì)浪費(fèi)很多的瀏覽器資源。那該怎樣做?我們真的不應(yīng)該使用它們嗎?讓我們考慮一些實(shí)用的東西。(關(guān)于CSS 3,51CTO推薦閱讀:定義未來(lái)Web樣式 CSS 3最新特性一覽)
實(shí)用性
我是這樣認(rèn)為的:不管怎樣,我們上面談?wù)摰淖罴褜?shí)踐都是有作用的。你可以遵守這些規(guī)則,因?yàn)樗麄儾⒉粫?huì)限制你CSS的能力。但也大可不必把它們當(dāng)作教條執(zhí)行。
如果你的網(wǎng)站正好非常緩慢,而你之前并沒(méi)有考慮過(guò)這些CSS最佳實(shí)踐,你可能需要好好檢查一下你的CSS了。如果你的網(wǎng)站沒(méi)有任何緩慢的跡象,那可以不用理它,以后寫(xiě)CSS時(shí)注意就好了。
極速卻不實(shí)用
我們知道了ID是最高效的選擇器。如果你想要一個(gè)渲染最快的網(wǎng)頁(yè),那你可以給頁(yè)面上每一個(gè)元素一個(gè)唯一的ID,然后樣式化每一個(gè)ID。這將會(huì)超級(jí)快,但也是極其滑稽的。這可能讓你的CSS文件很難讀很難維護(hù)。在一些對(duì)性能要求很高的硬編碼的網(wǎng)站上你都很難看到這種寫(xiě)法。我們不應(yīng)該為了效率而犧牲可讀性和可維護(hù)性。簡(jiǎn)單說(shuō)一點(diǎn),很多的JavaScript庫(kù)都使用了CSS選擇器,上面的原則也依然適用。ID是最快的,而復(fù)雜的后代選擇器會(huì)比較慢。
本文轉(zhuǎn)自abitno的博客,
原文地址:http://abitno.me/efficiently-rendering-css
【編輯推薦】