近期考慮對CSS進行一些重構,看著以前自己的代碼整個人凌亂了。于是做了一些調研,看到一些不一樣的地方給大家分享一下。
一、CSS的匹配規則
1、根據CSS定義位置來區別
平常所認為的優先級規則,從根本上來講是片面的。
默認樣式<外部樣式表<內部樣式表<行內樣式 //是片面的
瀏覽器默認樣式最低,行內樣式最高,這是肯定的。
但是外部樣式表和內部樣式表其實優先級并沒有太大的區別,只是我們一般都會在head中先引用外部樣式表,再定義內部樣式表,才形成了以上的觀點。(你完全可以把外部樣式表放到body的下面,雖然不太好但是規則是允許的)
對于所有的非行內自定義樣式(可以統一稱為樣式表),
樣式表的優先級完全取決于被引入或者定義的位置。
2、根據選擇器的優先級來確定
選擇器的優先級規則為:ID > 偽類 > 屬性 > 類 > 元素 > 通配符,對于組合選擇器的優先級就對以上規則從左到右依次進行比較,知道可以得出結果。
例如:#test_id div 則比#test_id .test_class的優先級要低。
通常為了保證樣式的準確性,我們會使用較高優先級的選擇器,或者使用多種選擇器的組合形式。
3、!important
最高優先級
二、CSS選擇器解析規則
前面講到,為了保證樣式應用的準確性,會使用多種選擇器的組合形式。于是,就有了一些比較極端的寫法——總是或者盡量使用更多層級的選擇器組合。
從準確性來看,毫無問題;從性能上看,這樣會有什么問題嗎?
顯然,這涉及到CSS的匹配規則。
1、從右到左的匹配規則
通常思維是選擇器指定越詳細,則越容易匹配,性能越好。這種觀點建立的基礎是,對每一個CSS樣式去查詢匹配dom中的節點,那么選擇器的詳細程度越高,就越能減少查詢的冗余,性能越好。例如:
.test_class .test_span1{} // 樣式1
.test_class .test_div1 .test_span1{} // 樣式2
// 布局
<div class="test_class">
<div class="test_div1"><span class="test_span1">測試1</span></div>
<div class="test_div2"><span class="test_span2">測試2</span></div>
</div>
按照上述規則,樣式1會比樣式2多做一次比較,即對test_span2的比較。
這種CSS查詢匹配dom節點的方式,就是常說的從左到右的匹配規則(針對CSS選擇器而言)——針對樣式1,從左到右匹配5次,從右到左匹配7次。
2、從右到左的匹配規則
還有一種思維是選擇器指定越精簡,則越容易匹配,性能越好。這種觀點建立的基礎是,對每一個dom節點去查詢匹配CSS中的樣式,那么選擇器的詳細程度越高,查詢匹配的次數就越多,性能越差。例如:
.test_div1 .test_span{} // 樣式1
.test_class .test_div1 .test_span{} // 樣式2
// 布局
<div class="test_class">
<div class="test_div1"><span class="test_span">測試1</span></div>
</div>
按照上述規則,針對“測試1”的樣式匹配,樣式1要比樣式2少1次匹配。這種dom節點查詢匹配CSS選擇器的方式,就是常說的從右到左的匹配規則(針對CSS選擇器而言)——針對樣式1,從左到右匹配3次,從右到左匹配2次。
3、CSS選擇器匹配規則
事實上雖然上述兩種匹配方式都有一定到理論性,但是結論只有一個——從右到左。至于原因,先來看一下一些有趣的回答。
3.1 哲學思維
人可以選擇兩條路,但是真正走的卻只有一條。
最根本的道理。
3.2 價值取向
英文順序一般先小后大,先具體后寬泛,例如姓名是先名后姓,地址是X號X街X城市X州、日期是日/月/年。
西方比較強調個體價值,中國比較強調家族觀念。
而從右到左正好符合了西方的個體價值觀。
——很性感的思維。
3.3、Sunday算法
這里只做了一個概述,具體的可以自己百科一下,還挺有意思的。
Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配。其核心思想是:在匹配過程中,模式串發現不匹配時,算法能跳過盡可能多的字符以進行下一步的匹配,從而提高了匹配效率。
而從右向左也正符合這一算法。
3.4、瀏覽器加載方式
訪問網頁的整個過程在瀏覽器的表現:
請求數據--詞法語法解析--下載link文件--生成dom樹--構建render樹--繪制
而CSS樣式的匹配正是在構建render樹時進行的,所以需要采用對每個dom節點查詢匹配CSS選擇器的方式,即從右到左的匹配規則(從1、2可以知道這樣匹配的次數較少)。
三、結論
很顯然,我們在定義樣式的選擇器時,在準確表達的情況下,應該盡量較少選擇器組合中的冗余,從一定程度上提升CSS的性能。