原文地址:Writing Efficient CSS for use in the Mozilla UI
以下文檔描述了應用在 Mozilla UI 中優化 CSS 文件的規則。第一部分是對於 Mozilla 樣式系統分類規則的一般性討論。在了解這個系統的基礎上,後續部分包含了一些指南,書寫可以利用這個樣式系統實踐優點的樣式的指南。
樣式系統把規則分為四大類。理解這些類是很重要的,因為對於規則的匹配來說他們是首先要考慮的。之後的段落中會使用“主選擇符”這個說法。主選擇符是指選擇符最右邊的部分(最終要匹配的那個元素,而不是它的祖先元素)。例如,在以下規則中:
a img, div > p, h1 + [title] {}
主選擇符是 “img”, “p”, 和 “[title]“。
ID 選擇符作為主選擇符的規則。
例如:
如果一條規則有一個指定的 class 作為主選擇符,就被歸入此類。
例如:
如果主選擇符不是 ID 或者 class,那麼下一個類很可能就是 tag 分類。如果一條規則指定 tag 為主選擇符,就被歸入此類。
例如:
除以上分類之外都歸入此類。
例如:
樣式系統從最右邊的選擇符開始向左側移動來匹配一條規則。樣式系統會一直向左匹配選擇符直到規則匹配完畢或者由於出錯停止匹配。
對於規則分類的第一步發生在主選擇符類別基礎上。這個分類的目的是把那些不需要浪費時間匹配的規則過濾出來。這是顯著提升性能的重點。對於一個給定的需要匹配的元素,規則越少,樣式的渲染越快。例如,元素有一個 ID,那麼只有和元素 ID 匹配的 ID 規則會被檢索。只有和元素的 class 匹配的 class 規則會被檢索。只有和 tag 匹配的 tag 規則會被檢索。全局規則總是會被檢索。
確保規則不以全局分類結束
如果有一條樣式規則是以 ID 選擇符為主選擇符的,就別再畫蛇添足的加上標簽名了。ID 都是唯一的,因此加上標簽名反而會無謂地拖慢匹配過程。(當有不同元素使用同一類名,而又需要動態地改變其中一個元素的類名來針對不同情況應用不同樣式時是個例外。)
和以上規則類似,所有的類名也是唯一的。標簽和類名連綴的寫法是一個慣例(但是,如果設計的變更使得需要改變標簽就會有靈活性的問題,因為也需要改變 class — 最好選用具有嚴格語義的名字,這種靈活性也是分離樣式表的目標之一)。
拖慢系統最大的一個原因是有太多的 tag 分類規則了。通過給元素增加類名,可以把這些 tag 類裡的規則分一部分去class 分類,就可以不需要浪費時間來試圖給一個標簽匹配那麼多的的規則了。
CSS 中,後代選擇符(descendant)[注1]的耗能高的可怕,尤其是選擇符的規則是在 tag 或者全局分類中。子選擇符(child selector)則經常是真正所需。如果沒有主題模塊所有者的明確允許,UI CSS 中禁止使用後代選擇符。
避免使用具有 tag 類規則的後代選擇符。這會明顯地增加匹配時間(尤其是這些規則會被多次匹配時)。
要小心使用子代選擇符。如果有別的方式可以不用,就不要用子選擇符。尤其是子選擇符被大量使用在 RDF 樹和類似的菜單中時。
要注意模版中來自 RDF 的屬性是可以復制的!可以利用這一點把 RDF 屬性復制到需要改變那個屬性的子元素上。
了解並使用那些可以繼承的屬性。XUL widgetry[注2] 已經明確設置了,因此可以把 list-style-image 或者 font 規則應用到父級標簽上,它將滲透進匿名內容。因此就不需要浪費時間為那些匿名內容寫規則了。
上例中,樣式化匿名內容的需求(沒有理解 list-style-image 可以繼承)導致了一條 class 類規則。其實這條規則應該屬於最明確的一類 — ID 類規則。
要記住,尤其是那些匿名內容,它們都有同樣的 class。上面那個不好的例子導致需要檢查每個菜單的圖標是否包含在 bookmarks 菜單項中。這是非常可怕的高昂消耗(有很多菜單);除 bookmarks 菜單之外,這條規則不應該被其他任何菜單想檢查。
把一堆圖片放到一個單獨的圖片文件中,並用 -moz-image-region[注3] 選中會有顯著的性能提升。()
注1: 後代選擇符(descendant selector) 子選擇符(child selector) 是有區別的。單從字面來講,後代選擇符,顧名思義包括兒子、孫子、重孫子等所有後代; 子選擇符只是指兒子,就不管那幫孫子了。
注2: XUL widgetry 不清楚是啥。
注3: 貌似想法和現在說的 CSS sprites 方法差不多,要知道這可是十年前(2000年)的文章啊。 – 糖伴西紅柿