前言:MDN上有寫關于如何高效的css的文章,此文主要參考其做了記錄(也可以理解為是翻譯)。
css規范并不會強行規定瀏覽器必須如何實現樣式系統,只會規定瀏覽器必須實現什么。因此,不同的樣式系統引擎擁有不同的性能,開源的 Gecko和Webkit算法類似,因此優缺點也類似。因此,下面的建議在大部分的web瀏覽器上應該是有意義的。
第一部分簡單介紹樣式系統規則分類;后面的章節主要指導如何利用樣式系統的實現原理,來書寫更有效率的規則。
樣式系統如何建立規則
樣式系統的規則分為四大類
- ID
- class
- tag
- 通用規則
理解這四類規則非常關鍵,這是規則匹配的基礎。
在接下來的段落中,我會使用"關鍵選擇“(key selector)術語。key selector是選擇器的最后一部分。
例如,在下面的規則中:
a img, div > p, h1 + title {...}
key selector是img,p和title。
ID rules
第一類是使用ID選擇器作為key selector.
button#backButton {…} /* This is an ID-categorized rule */
#urlBar[type="autocomplete"] {…} /* This is an ID-categorized rule */
treeitem > treerow > treecell#myCell:active {…} /* This is an ID-categorized rule */
Class rules
第二類是使用了class選擇器作為key selector
button.toolbarButton {…} /* A class-based rule */
.fancyText {…} /* A class-based rule */
menuitem > .menu-left[checked="true"] {…} /* A class-based rule */
Tag rules
如果既不是class也不是ID作為key selector,下一個候選是tag。
td {…} /* A tag-based rule */
treeitem > treerow {…} /* A tag-based rule */
input[type="checkbox"] {…} /* A tag-based rule */
Universal rules
剩下的均為此類。
[hidden="true"] {…} /* A universal rule */
* {…} /* A universal rule */
tree > [collapsed="true"] {…} /* A universal rule */
樣式系統如何匹配規則
樣式系統從key selector開始匹配,然后向左繼續,尋找選擇器的任意祖先。只要選擇器的子樹繼續導出(這樣翻譯感覺怪怪的),樣式系統會繼續往左移動,直到要么匹配規則,要么因為不匹配終止。
最基本的概念是了解規則過濾。這些類別存在的目的是過濾掉不相關的規則,這樣樣式系統不用浪費時間去匹配它們。
這是提升性能的關鍵:檢查一個指定的元素,規則越少,系統解析就越快。
例如,如果元素指定了ID,那么只有與元素ID相同的ID rule會進行檢查。只有存在于元素class列表的class 規則才會進行檢查。只有與標簽相同的tag rule會被進行檢查。通用規則總是會被檢查。
高效css建議
避免使用通用規則
避免一個規則的結束是通用規則這一類。
不要使用tag或者class修飾ID rule
如果一個規則使用了ID選擇器作為key selector,不要再添加tag標簽指定。因為ID是唯一的,增加tag name會增加不必要的額外的匹配工作。
BAD
button#backButton {…}
BAD
.menu-left#newMenuIcon {…}
GOOD
#backButton {…}
GOOD
#newMenuIcon {…}
例外:當需要通過改變元素的class來應用不同的樣式,但是同樣的class將會被其他元素共享。
不要使用tag修飾class規則
盡管class可以在同一個頁面重復出現,但是它的唯一性比tag更強。
你可以約定在class名稱中包含tag名稱,但是這會損失一些靈活性。當設計改變tag時,class也會跟著變化。最好的是使用語義名稱的class name。
BAD
treecell.indented {…}
GOOD
.treecell-indented {…}
BEST
.hierarchy-deep {…}
使用最特定的一類規則
tag這類會匹配太多的規則,這會大大的降低效率。通過給元素增加class,我們可以回class分類進行細分,減少匹配時間。
BAD
treeitem[mailfolder="true"] > treerow > treecell {…}
GOOD
.treecell-mailfolder {…}
避免使用后代選擇器
后代選擇器是css中最耗時的選擇器。尤其當選擇器是tag或者通用這一類。
BAD
treehead treerow treecell {…}
BETTER, BUT STILL BAD (see next guideline)
treehead > treerow > treecell {…}
tag分類規則永遠不要包含孩子選擇器
避免使用孩子選擇器在tag分類規則中。這會顯著增長匹配時間。
BAD
treehead > treerow > treecell {…}
GOOD
.treecell-header {…}
質疑所有使用孩子選擇器的地方
使用孩子選擇器時務必謹慎,盡可能避免使用。
特別是,子選擇器頻繁適用于RDF樹(這個自行Google吧)和menus,如下:
BAD
treeitem[IsImapServer="true"] > treerow > .tree-folderpane-icon {…}
依靠繼承
了解哪些屬性繼承,然后使用繼承。
BAD
#bookmarkMenuItem > .menu-left { list-style-image: url(blah) }
GOOD
#bookmarkMenuItem { list-style-image: url(blah) }
Use -moz-image-region
這條個人感覺不靠譜
Use scoped stylesheets
這條個人感覺不好維護
除非必要,不要使用特定瀏覽器特性
這條個人感覺意義不大
推薦閱讀:
MDN Writing efficient CSS
Performance improvement by writing efficient CSS selector