CSS選擇器原理
瀏覽器是如何讀取選擇器,以識別樣式,并將相應的樣式附于對應的HTML元素,達到美化頁面的效果。Chris
Coyier曾在《Efficiently Rendering CSS》一文中說過“瀏覽器讀取你的選擇器,遵循的原則是從選擇器的右邊到左邊讀取。換句話說,瀏覽器讀取選擇器的順序是由右到左進行”。比如說:
div.nav > ul li a
上面的實例來說,瀏覽器首先會嘗試在你的HTML標簽中尋找“a”元素,接著在匹配“li和ul”,最后在去匹配“div.nav”。這就是前成所主的“選擇器從右到左的原則”。
選擇器的最后一部分,也就是選擇器的最右邊(在這個例子中就是a[title]部分)部分被稱為“關鍵選擇器”,它將決定你的選擇器的效率如何?是高還是低。
老版本的瀏覽器可以過濾掉不匹配的選擇器,而直接匹配更高效的選擇器。記得David Hyatt在《Writing efficient CSS for use in the Mozilla UI》說過:“這個關鍵選擇器可以大大提高選擇器的性能,少檢查一個給定的元素規則,就可以更有效的將樣式匹配給對應的HTML元素。”那么如何讓關鍵選
擇器更有效,性能化更高呢?其實很簡單,主要把握一點“越具體的關鍵選擇器,其性能越高”
提高選擇器效率
那么什么樣類型的選擇器,其性能高?什么樣的類型的選擇器性能低呢?下面我們就針對兩個問題來展開具體的學習。
CSS選擇器的效率
如果你閱讀了本站的有關于選擇器類型的介紹的話,你對選擇器并不會感到陌生。就算你沒讀過,我想CSS選擇器不會讓我們覺得是新東西,比如我們
常用的基本選擇器“元素標簽選擇器div”、“id選擇器#header”、“類選擇器.class”,或者說我們很少見的偽類選擇器“:focus”以
及更復雜的css3選擇器“:nth-child”等等。
選擇器有一個固有的效率,我們來看Steve Souders給排的一個順序:
id選擇器(#myid)
類選擇器(.myclassname)
標簽選擇器(div,h1,p)
相鄰選擇器(h1+p)
子選擇器(ul > li)
后代選擇器(li a)
通配符選擇器(*)
屬性選擇器(a[rel="external"])
偽類選擇器(a:hover,li:nth-child)
上面九種選擇器的效率是從高到低排下來的,基中ID選擇器的效率是最高,而偽類選擇器的效率則是最底。詳細的介紹大家還可以點擊Writing efficient CSS selectors。
綜合上面的順序,我們清楚的知道,id和類名用于關鍵選擇器上效率是最高的,而CSS3的仿偽類和屬性選擇器,雖然使用方便,但其效率卻是最低的。我們下面一起來看幾個實例的對比:
div #myid
效率要比下面的高:
#myid div
第一種選擇器比第二種選擇器效率高,大家或許會問為什么?其實根據前面所介紹的我們就不難理解了,因為第一個選擇器的“關鍵選擇器”使用了
“ID選擇器”,而第二個選擇器的“關鍵選擇器”使用的是“標簽選擇器”,對比下來,“ID選擇器”效率高過“標簽選擇器”,所以說第一個選擇器的效率要
高于第二個選擇器。
在類名或ID名前面加上標簽也會致使選擇器效率變低的,比如說:
div
myid
上面兩個選擇的效率要高于下面的選擇器:
p#mydiv
p.myclassname
來自Mozilla的幾點建議
David在《Use efficient CSS selectors》中介紹了幾種書寫高效率的CSS選擇器的方法,下面我將他們移到這里來讓大家參考:
寫道
1 避免普遍規則
2 不要在ID選擇器前加標簽名或類名
3 不要在類名選擇器前加標簽名
4 盡可能使用具體的類別
5 避免使用后代選擇器
6 標簽分類規則中不應該包含一個子選擇器
7 子選擇器的問題
8 借助相關繼承關系
9 使用范圍內的樣式表
如果你不夠清楚上面所講的是什么,你可以點擊這里,他會讓你更容易了解這些規則。
我們應該怎么做
前面說“ID選擇器”的效率是最高的,那么今天我們寫樣式,為了提高選擇器的效率,是不是我們要在每一個文檔的HTML元素中都加入ID名呢?
我想這樣的做法是沒有的。對于一個有語義的代碼編寫和如何提高性能,以前他們之間如何的平衡?其實這個選擇器的效率低一點,對于大多數網站來說并不會有太
大的影響,但對于一個大型的網站,產生大量的流量這就會有差別了,也就很值得我們去對他進行優化。那么我們就很有必要的去了解他們是如何工作,比如說,一
般情況下哪些選擇器的使用效率更高。來看兩個簡單的例子:
#myid
上面的選擇器高于下面的:
p#myid
后者的寫法我發現還是有很多朋友這樣寫,但我不知道你為什么需要在ID前面加一個標簽?難道你同一個頁面會有多個相同的ID不成?
我們接下來在來看一個實例,用于列表上的,比如說我們制作導航菜單的:
#nav a
高效于:
#nav li a
上面只是介紹了兩個常碰到的實例,在這里說這兩個實例,主要目的是讓你在今后的編寫樣式時,能注意這方面的的細節,從而加快你的代碼效率。