css選擇器為什麼是從右到左解讀的

antzone發表於2017-04-02

可能很多朋友都認為css的選擇器是從左到右解讀的,如下程式碼:

[CSS] 純文字檢視 複製程式碼
div p a{
  /*code*/
}

可能很多人都認為順序是這樣的,那就是從div檢查,然後是p,最後是a,由此來確定元素是不是應用此css樣式。

事實並非如此,css選擇器是從右到左進行檢查匹配的,這主要是為了效率考慮,下面就進行以下介紹。

瀏覽器的渲染過程以谷歌瀏覽器為例,大致如下圖:

a:3:{s:3:\"pic\";s:43:\"portal/201704/02/094958dz8klx3kz37lu1l3.jpg\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

HTML經過解析生成DOM Tree;在CSS解析完畢後,需要將解析的結果與DOM Tree的內容一起進行分析建立一棵 Render Tree,最終用來進行繪圖。Render Tree中的元素(WebKit 中稱為renderers,Firefox下為frame)與DOM元素相對應,但非一一對應:

(1).一個 DOM 元素可能會對應多個 renderer,如文字折行後,不同的行會成為render tree種不同的renderer。

(2).有些DOM元素被Render Tree完全無視,比如 display:none的元素。在建立Render Tree時(WebKit 中的「Attachment」過程),瀏覽器就要為每個DOM Tree中的元素根據 CSS 的解析結果(Style Rules)來確定生成怎樣的 renderer。對於每個DOM元素,必須在所有Style Rules中找到符合的 selector 並將對應的規則進行合併。選擇器的解析實際是在這裡執行的,在遍歷 DOM Tree 時,從Style Rules中去尋找對應的selector。有時候css程式碼的數量是相當龐大的,但是對於單個DOM元素來說,也許只有幾個選擇器是匹配的,也就是說能夠匹配的css選擇器絕大多數情況下是佔少數的,所以我們需要選擇一個更為高效的方式來確定哪些css選擇器是匹配的,下面就分別對比一下從左到右和從右到左的的效率問題。以如下選擇器為例子:

[CSS] 純文字檢視 複製程式碼
div > div p em

如果有是從左到右,首先就要檢查當前元素到html的整條路徑,找到最上層的 div,再往下找,如果遇到不匹配就必須回到最上層那個 div,往下超找div去匹配選擇器中的第一個div,回溯若干次才能確定匹配與否,效率很低。

逆向匹配則不同,如果當前的DOM元素不是selector最後的em,那隻要一步就能排除。只有在匹配時,才會不斷向上找父節點進行驗證,這樣效率是不是會高很多。

相關文章