從css到頁面樣式渲染

寫了這麼多class,color,background,display...; 也許有時候會疑惑,怎麼就顯示在頁面上,改變元素的樣式。css

本文簡明介紹整個解析,匹配,渲染過程html

css 描述

css 是Cascading Style Sheets的簡寫,是一種樣式表語言。對應多種語法規則,能夠爲HTML 指定樣式。前端

基本規則

圖片描述

圖片來源html5

css 規則由兩部分組成:選擇器聲明。上圖中element 對應的類選擇器,緊接着聲明(Declaration)web

每條聲明由一個屬性(Property)冒號(:)和 一個值(value)分號(;) 組成。chrome

CSS 解析

解析 html 或外部css 文檔,就是將文檔轉化成爲有意義的結構,可以讓代碼理解。解析結果表明了文檔結構的節點樹,瀏覽器

解析分爲詞法分析 和 語法分析。
解析過程性能優化

詞法分析,也是編譯原理中的術語,從左到右一個字符一個字符的讀入源程序,對字符流進行掃描,根據構詞規則識別單詞,。這一過程可使用lex等工具自動生成。app

語法分析,主要任務是在詞法分析的基礎上,將單詞序列組合成各種語法短語,如「程序」, 「語句」,「表達式」dom

解析工做一般會被拆分爲兩個組件:

  1. 詞法分析器,負責將輸入流分解成有效的字符。
  2. 解析器,負責根據不一樣語言的語法規則來分析文檔結構,最後構造出解析樹。
    詞法分析器知道如何去除不相關的字符,好比空格和換行

具體到css解析,由於它是上下文無關的語法,能夠利用各類解析器進行解析。webkit 使用Flex 和 Bison 解析器生成器,經過css 語法文件自動建立解析器。解析器將CSS文件解析成StyleSheet對象,且每一個對象都包含CSS規則。CSS規則包含選擇器和聲明對象。
圖片描述

上圖是 一個像素點的一輩子的ppt中選出圖片,感興趣能夠看看演講視頻,很是直白,css樣式規則會被各類方式索引以便進行快速有效的查找。實現各個樣式屬性的C++ 類,好比ppt中的BorderLeftColor類,是在構建時Python腳本自動生成的。

具體到代碼實現中,webkit 使用CSSRuleSet 對象來保存style rule,在通常規則須要建立時,調用createStyleRule();

瀏覽器從右往左匹配選擇器

在使用css選擇器進行樣式匹配時,儘可能少用層級關係,由於這樣能夠減小選擇器匹配的次數,提升css 解析效率。

其實瀏覽器使用從右到左的解析順序,一樣提升了效率。一般在寫css 樣式時,咱們一向的想法是,從左往右解析,從根節點開始,一層一層遍歷匹配,直到全部的選擇器都匹配上了。瀏覽器解析的順序正好相反。

從右往左匹配的好處

簡單回顧下本次話題的上下文,也就是瀏覽器對頁面解析過程:

  1. HTML parser 生成 Dom Tree
  2. css parser 生成 style rules,也就是CSSOM tree。
  3. DomCSSOM匹配完成後,最後結合生成render tree
  4. 根據 render tree 開始 佈局
    ...

clipboard.png

根據這張圖,能夠對渲染過程大體瞭解。

回到瀏覽器匹配css 規則上,若是隻有一個選擇器 對應匹配一個元素,從左往右匹配看似很是合理,可是正常狀況是,一個dom節點,好比<div class="cls1 cls2 cls3" id='id1'></div>,可能對應了無數個css規則,沒有上限,我能夠在上面加很是多的樣式。css 匹配效率的關鍵就是如何快速判斷儘量多的選擇器並不能匹配。

先看看有多層嵌套的css規則。好比 #root .box .wrap i {}, 若是從左往右解析,最左邊開始, 直到最右邊的選擇器i, dom節點上根本沒有i標籤, 遍歷到最後才排除css 規則。

相反,從最右邊的選擇器部分開始匹配,若是不成功,整個匹配過程就能夠馬上結束;成功了,繼續往左,匹配父節點,跟樹的深度成正比。因此瀏覽器的匹配方式,能夠很是快速的排除大部分的選擇器。

根據2009年在Firefox上作的測試,結論是僅僅從最右邊的選擇器開始檢查,就能夠排除70%的規則。快速除去2/3的css規則後,後面只用擔憂剩餘的1/3。

樣式做用在DOM元素上

從css文檔被解析器解析完成,將數據保存在對象模型中,獲取全部已解析的樣式規則,結合瀏覽器提供的默認樣式,計算出每一個DOM 元素最終的樣式值。保存在ComputedStyle對象模型中,它是由樣式屬性和值造成的map。
而且getComputedStyle 已經暴露出來,在js中經過window.getComputedStyle,能夠獲取元素的最終樣式。

共享ComputedStyle

若是多個element的computedStyle不經過計算能夠確認它們相等,那麼這些elements只會計算一次樣式,其他的直接共享該ComputedStyle。

那些規則會共享computedStyle(待驗證):

  1. 該共享的element不能有id 屬性且CSS中還有該id的StyleRule,即便StyleRule 與 element 不匹配
  2. tagName 和 class 屬性必須同樣。
  3. mappedAttribute 必須相同。
  4. 不能使用sibling selector, 好比 :first-child, :last-child.
  5. 不能有style 屬性,哪怕style 屬性相同。他們也不會共享。

    <p style="color:red">p1</p>
       <p style="color:red">p2</p>

渲染

頁面繪製到屏幕後,頁面結構的改變也有可能致使渲染樹從新計算,其中重排和重繪是最耗時的部分。

在頁面的生命週期中,隨時都有可能發生重排(Layout)和重繪(Painting)

重排(reflow)

當可見節點位置 及尺寸發生變化時都會發生重排,並且重排開銷比重繪更大。

至少會有一次重排,發生在初始化頁面佈局的時候。

觸發重排的幾種狀況:

  1. 添加或刪除可見dom元素
  2. 元素位置改變
  3. 元素尺寸改變,
  4. 文字,內容,字體發生改變
  5. 頁面初始化渲染
    ....

重繪(repaints)

改變元素的外觀屬性(如background-color, border-color, visibility),不影響整個佈局,瀏覽器就會根據元素的新屬性從新繪製。

重繪不會帶來從新佈局

層合成(composite)

DOM樹中每一個節點的都對應一個LayoutObject, 擁有相同的座標空間的LayoutObject,屬於同一渲染層(RenderLayers)。

渲染層保證元素按照正確順序合成(composite),正常展現元素的重疊以及元素透明等。

存在一些特殊狀況,爲知足指定條件的LayoutObject會擁有獨立的渲染層,其餘layoutobject則和第一個擁有渲染層的父元素公用一個。

利用chrome Devtools查看繪製過程。

打開Chrome Devtools,按下Esc建
在出現的面板上 點擊左上角三點。
clipboard.png

選擇rendering,轉到對應標籤。
clipboard.png

打開後,頁面中閃爍的綠色區域,表示這塊須要從新繪製。
當滾動側邊欄時,會出現整塊綠色

clipboard.png

總結

本文對css整個渲染過程進行簡單介紹,試圖把大量複雜知識點串在一塊兒,至少可讓平時跟css打交道的咱們,瞭解大體是個什麼過程,同時也是對本身學習過程當中的一次總結。對於裏面涉及到的概念,均可以做爲一個切入點,去好好研究。

參考連接

  1. Things nobody ever taught me about CSS
  2. 縮小樣式計算的範圍並下降其複雜性
  3. 爲何瀏覽器讀取css規則的順序是從右到左
  4. why-do-browsers-match-css-selectors-from-right-to-left
  5. 【Hello CSS】第一章-CSS的語法與工做流
  6. 編譯原理之詞法分析、語法分析、語義分析
  7. How Browsers Work: Behind the scenes of modern web browsers
  8. 前端代碼如何經過瀏覽器演化爲屏幕顯示的像素
  9. Webkit CSS引擎分析
  10. 簡化繪製的複雜度、減少繪製區域
  11. 無線性能優化:Composite
相關文章
相關標籤/搜索