瀏覽器解析css選擇器的規則

瀏覽器解析css選擇器的規則是從右向左的,這樣會提高查找選擇器所對應的元素的效率。

中國人有一個習慣,不論幹什麼,潛意識中的順序都是從左到右,從上到下,從大到下,因此大多數人看到這個順序都會感到很不適應,但大家要記得我們這是一個程序,而程序是用來幹什麼的?運行。因此它的第一要領是必須效率高,因此所謂的習慣我們就先拋到九霄雲外去。

至於具體分析如下(個人理解):

1.html片段如下

<div id="div1">
    <div id="div2">
    <p class="p1"><span>1</span><span>2</span><span class="green">3</span></p>

    <p class="p1"><span>11</span><span class="red">11</span><span>11</span></p>
</div>
    <div id="div3">
        <p><span>z</span><span>we</span><span>rewr</span></p>
        <p><span>z</span><span>we</span><span>rewr</span></p>
    </div>
    <div id="div4">
        <p><span>12</span><span>dwe</span><span>ef</span></p>
        <p><span>14</span><span>weef</span><span class="red">34123</span></p>
    </div>
</div>

而我們CSS選擇器是 div div p.p1 span.red{color:red},如果從左到右一層一層的篩選:首先會看到很多div被篩選出來,接下來篩選每一個div,首先在#div2中看到了class=p1的p,此時我們很是高興,感覺勝利就在前方了,再看class=p1的p標籤的子元素,看到第一個很是失望,不符合span.red,不要急,再看下一個又不符合規則,小小的安慰自己一下,最後一個含有class,說不定就是了,結果,結果居然class=green,此時火冒三丈,就差最後一層,怎奈居然出現這種事,無奈之下只能在返回#div2繼續匹配它的子元素....

但如果我們換一個思路,首先匹配class=red 的 span,我們找到2個符合條件的的span然後在和上一次比對,我們需要的是span.red 是 p.p1的下屬元素,此時就發現剛纔篩選出來的第二個 span 元素不符合要求,再來匹配第一個,層層向上匹配,恭喜你,最終匹配成功,就實現瞭如下效果:


至於詳細的過程可以參考下圖:(圖片來自http://www.cnblogs.com/aaronjs/p/3300797.html

更爲專業的解釋:

  • HTML 經過解析生成 DOM Tree(這個我們比較熟悉);而在 CSS 解析完畢後,需要將解析的結果與 DOM Tree 的內容一起進行分析建立一棵 Render Tree,最終用來進行繪圖。Render Tree 中的元素(WebKit 中稱爲「renderers」,Firefox 下爲「frames」)與 DOM 元素相對應,但非一一對應:一個 DOM 元素可能會對應多個 renderer,如文本折行後,不同的「行」會成爲 render tree 種不同的 renderer。也有的 DOM 元素被 Render Tree 完全無視,比如 display:none 的元素。
  • 在建立 Render Tree 時(WebKit 中的「Attachment」過程),瀏覽器就要爲每個 DOM Tree 中的元素根據 CSS 的解析結果(Style Rules)來確定生成怎樣的 renderer。對於每個 DOM 元素,必須在所有 Style Rules 中找到符合的 selector 並將對應的規則進行合併。選擇器的「解析」實際是在這裏執行的,在遍歷 DOM Tree 時,從 Style Rules 中去尋找對應的 selector。
  • 因爲所有樣式規則可能數量很大,而且絕大多數不會匹配到當前的 DOM 元素(因爲數量很大所以一般會建立規則索引樹),所以有一個快速的方法來判斷「這個 selector 不匹配當前元素」就是極其重要的。
  • 如果正向解析,例如「div div p em」,我們首先就要檢查當前元素到 html 的整條路徑,找到最上層的 div,再往下找,如果遇到不匹配就必須回到最上層那個 div,往下再去匹配選擇器中的第一個 div,回溯若干次才能確定匹配與否,效率很低。
  • 逆向匹配則不同,如果當前的 DOM 元素是 div,而不是 selector 最後的 em,那隻要一步就能排除。只有在匹配時,纔會不斷向上找父節點進行驗證。
  • 但因爲匹配的情況遠遠低於不匹配的情況,所以逆向匹配帶來的優勢是巨大的。同時我們也能夠看出,在選擇器結尾加上「*」就大大降低了這種優勢,這也就是很多優化原則提到的儘量避免在選擇器末尾添加通配符的原因。

 簡單的來說瀏覽器從右到左進行查找的好處是爲了儘早過濾掉一些無關的樣式規則和元素



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章