寫了這麼多class,color,background,display...
; 也許有時候會疑惑,怎麼就顯示在頁面上,改變元素的樣式。css
本文簡明介紹整個解析,匹配,渲染過程html
css 是Cascading Style Sheets的簡寫,是一種樣式表語言。對應多種語法規則,能夠爲HTML 指定樣式。前端
圖片來源。 html5
css 規則由兩部分組成:選擇器
和 聲明
。上圖中element
對應的類選擇器
,緊接着聲明(Declaration)
。web
每條聲明由一個屬性(Property)
加冒號(:)
和 一個值(value)
加分號(;)
組成。chrome
解析 html 或外部css 文檔,就是將文檔轉化成爲有意義的結構,可以讓代碼理解。解析結果表明了文檔結構的節點樹,瀏覽器
解析分爲詞法分析 和 語法分析。性能優化
詞法分析,也是編譯原理中的術語,從左到右一個字符一個字符的讀入源程序,對字符流進行掃描,根據構詞規則識別單詞,。這一過程可使用lex等工具自動生成。app
語法分析,主要任務是在詞法分析的基礎上,將單詞序列組合成各種語法短語,如「程序」, 「語句」,「表達式」dom
解析工做一般會被拆分爲兩個組件:
具體到css解析,由於它是上下文無關的語法,能夠利用各類解析器進行解析。webkit 使用Flex 和 Bison 解析器生成器,經過css 語法文件自動建立解析器。解析器將CSS文件解析成StyleSheet對象,且每一個對象都包含CSS規則。CSS規則包含選擇器和聲明對象。
上圖是 一個像素點的一輩子的ppt中選出圖片,感興趣能夠看看演講視頻,很是直白,css樣式規則會被各類方式索引以便進行快速有效的查找。實現各個樣式屬性的C++ 類,好比ppt中的BorderLeftColor類,是在構建時Python腳本自動生成的。
具體到代碼實現中,webkit 使用CSSRuleSet 對象來保存style rule,在通常規則須要建立時,調用createStyleRule();
在使用css選擇器進行樣式匹配時,儘可能少用層級關係,由於這樣能夠減小選擇器匹配的次數,提升css 解析效率。
其實瀏覽器使用從右到左的解析順序,一樣提升了效率。一般在寫css 樣式時,咱們一向的想法是,從左往右解析,從根節點開始,一層一層遍歷匹配,直到全部的選擇器都匹配上了。瀏覽器解析的順序正好相反。
簡單回顧下本次話題的上下文,也就是瀏覽器對頁面解析過程:
HTML parser
生成 Dom Tree
css parser
生成 style rules
,也就是CSSOM tree。Dom
與 CSSOM
匹配完成後,最後結合生成render tree
。根據這張圖,能夠對渲染過程大體瞭解。
回到瀏覽器匹配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。
從css文檔被解析器解析完成,將數據保存在對象模型中,獲取全部已解析的樣式規則,結合瀏覽器提供的默認樣式,計算出每一個DOM 元素最終的樣式值。保存在ComputedStyle對象模型中,它是由樣式屬性和值造成的map。
而且getComputedStyle 已經暴露出來,在js中經過window.getComputedStyle
,能夠獲取元素的最終樣式。
若是多個element的computedStyle不經過計算能夠確認它們相等,那麼這些elements只會計算一次樣式,其他的直接共享該ComputedStyle。
那些規則會共享computedStyle(待驗證):
不能有style 屬性,哪怕style 屬性相同。他們也不會共享。
<p style="color:red">p1</p> <p style="color:red">p2</p>
頁面繪製到屏幕後,頁面結構的改變也有可能致使渲染樹從新計算,其中重排和重繪是最耗時的部分。
在頁面的生命週期中,隨時都有可能發生重排(Layout)和重繪(Painting)
當可見節點位置 及尺寸發生變化時都會發生重排,並且重排開銷比重繪更大。
至少會有一次重排,發生在初始化頁面佈局的時候。
觸發重排的幾種狀況:
改變元素的外觀屬性(如background-color, border-color, visibility),不影響整個佈局,瀏覽器就會根據元素的新屬性從新繪製。
重繪不會帶來從新佈局
DOM樹中每一個節點的都對應一個LayoutObject, 擁有相同的座標空間的LayoutObject,屬於同一渲染層(RenderLayers)。
渲染層保證元素按照正確順序合成(composite),正常展現元素的重疊以及元素透明等。
存在一些特殊狀況,爲知足指定條件的LayoutObject會擁有獨立的渲染層,其餘layoutobject則和第一個擁有渲染層的父元素公用一個。
打開Chrome Devtools,按下Esc建
在出現的面板上 點擊左上角三點。
選擇rendering,轉到對應標籤。
打開後,頁面中閃爍的綠色區域,表示這塊須要從新繪製。
當滾動側邊欄時,會出現整塊綠色
本文對css整個渲染過程進行簡單介紹,試圖把大量複雜知識點串在一塊兒,至少可讓平時跟css打交道的咱們,瞭解大體是個什麼過程,同時也是對本身學習過程當中的一次總結。對於裏面涉及到的概念,均可以做爲一個切入點,去好好研究。