1. 程式人生 > >為什麽CSS選擇器是從右往左解析

為什麽CSS選擇器是從右往左解析

解析器 就會 視頻 rac 廠商 bar ... {} -html

2016年08月05日 09:38:40 閱讀數:3752

一、CSS選擇器的解析順序

相信很多人在一開始接觸CSS的時候都會看到一條規則就是盡量少使用層級關系,比如盡量不要寫成:

#div P.class {
    color: red;
}
  • 1
  • 2
  • 3

而是寫成:

.class {
    color: red;
}
  • 1
  • 2
  • 3

之所以需要這麽寫,給的解釋是這樣可以減少選擇器匹配的次數(推薦一個CSS規範的網站)。初看覺得哦,有點道理啊,但是往細了再想想:如果我把層級定的足夠的清晰分明,那不是可以直接去掉很多不對應的CSS選擇器的索引路徑的麽?為什麽都是建議少使用層級關系呢?

原因其實很簡單,我們犯了一個經驗主義錯誤,默認CSS選擇器是從左往右進行解析的,實際上恰恰相反,CSS選擇器是從右往左解析的。

這個事實是不是很顛覆一般的認識?可能這裏很多人就要問了,為什麽瀏覽器廠商要搞出這種反人類的解析順序?難道CSS也跟JS一樣當初幾個瀏覽器廠商互相之間大打出手怎麽讓你別扭怎麽來?這裏這個鍋就不讓巨硬背了(巨硬:怎麽老是我。。。),其實之所以要這麽做是為了更快的找到對應的樣式,這裏我推薦一下winter老師的一個分享,這篇文章說白了只能算是這個視頻的一篇筆記罷了。。。

二、CSS選擇器進行優化的必要性

OK,具體的情況具體分析,我們先來看一看瀏覽器的渲染過程,如圖:


技術分享圖片

在圖中我們可以看到HTML解析出了一顆DOM tree,與此同時樣式腳本則解析生成了一個style rules,也可以說是一個CSS tree。最後,DOM tree同style rules一同結合解析出一顆Render Tree,而Render Tree就是包含了一個dom對象以及為其計算好的樣式規則,提供了布局以及顯示方法。

因為不清楚一個DOM對象上究竟對應著哪些樣式規則,所以只能選擇一個最笨的辦法,即每一個DOM對象都遍歷一遍style rules,DOM對象的數量相信大家也都清楚,如果每次遍歷style rules都是像一個曬太陽的老大爺一樣的悠哉遊哉,那麽鼠標廠商應該會很開心,嗯,摔壞了正好買新的嘛~~~因此對CSS選擇器進行優化就是一個必須的事情了。

三、從右往左解析到底好在哪裏

假如有如下的一段HTML:

<div id="div1">
    <div class="a">
        <div class="b">
            ...
        </div>
        <div class="c">
            <div class="d">
                ...
            </div>
            <div class="e">
                ...
            </div>
        </div>
    </div>
    <div class="f">
        <div class="c">
            <div class="d">
                ...
            </div>
        </div>
    </div>
</div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

和如下的CSS:

#div1 .c .d {}
.f .c .d {}
.a .c .e {}
#div1 .f {}
.c .d{}
  • 1
  • 2
  • 3
  • 4
  • 5

假如我們的CSS解析器是從左往右進行匹配的,那麽會生成如下的style rules:


技術分享圖片

首先,#div1 .c .d {} .f .c .d {}.c .d{}這三個選擇器裏面都含有 .c .d{}這麽一個公用樣式,所以哪怕是我們的DOM節點明確了是在#div1下面都必須對style rules進行全部的匹配查找,這樣一來基本上可以說是每一個DOM節點都必須完全遍歷一遍style rules,不然搞不好就會漏掉一些公用樣式之類的,所以想著將層級寫的更加詳細就能去掉很多不對應的CSS選擇器的索引路徑的就不要想了,不管你寫的多細,你總是需要把整個style rules都遍歷一遍,不然萬一漏掉了某個公用樣式不就思密達了?

那麽如果我們換成從右向左進行解析就能夠避免這種情況了麽?請看下面這個style rules:


技術分享圖片

別的先不提,最少這個節點就少了很多嘛,哪怕我這裏同樣是需要全部遍歷一遍就沖著減少了這麽多個節點也要從右往左進行解析啊!

更重要的是,只要有公用樣式,那麽選擇器最右邊的那個類型選擇器一定是相同的,如此公共樣式就很自然的都集中到一個分支上,這個時候我們完全可以將其他不匹配的路徑全部去掉而不用擔心會漏掉某些個公用樣式了。雖然當這顆CSS樹在遍歷的時候還有有部分節點會遍歷到最後才能確定到底是不是匹配的,但總的來說從右往左進行解析還是會比從左往右解析要少很多次的匹配,這樣帶來的效率提升是顯而易見的!

同時,這也是不建議使用*通配符來進行樣式匹配的原因:瀏覽器專門建立了一個反常規思維的從右往左的匹配規則就是為了避免對所有元素進行遍歷,你直接一個通配符等於之前的工作都白做了。

最後,從右往左進行解析還有一個好處那就是從右往左進行匹配的時候,匹配的全部是DOM元素的父節點,而從左往右進行匹配的時候時候,匹配的全部是DOM元素的子節點,這樣就避免了HTML與CSS沒有下載完需要進行等待的情形。

以上就是我所理解的為什麽CSS選擇器是從右往左解析的原因,如有錯誤歡迎大家進行指正。

為什麽CSS選擇器是從右往左解析