瀏覽器渲染原理 記錄備份

解析HTML以構建DOM樹 —— 構建render樹 —— 佈局render樹 —— 繪製render樹

 

一、構建DOM樹(parse):渲染引擎解析HTML文檔,首先將標籤轉換成DOM樹中的DOM node(包括js生成的標籤)生成內容樹(Content Tree/DOM Tree);javascript

 

二、構建渲染樹(construct):解析對應的CSS樣式文件信息(包括js生成的樣式和外部css文件),而這些文件信息以及HTML中可見的指令(如<b></b>),構建渲染樹(Rendering Tree/Frame Tree);php

 

三、佈局渲染樹(reflow/layout):從根節點遞歸調用,計算每個元素的大小、位置等,給出每一個節點所應該在屏幕上出現的精確座標;每當一個新元素加入到這個dom樹當中,瀏覽器便會經過css引擎查遍css樣式表,找到符合該元素的樣式規則應用到這個元素上。css

 

四、繪製渲染樹(paint/repaint):遍歷渲染樹,使用UI後端層來繪製每一個節點。html

 

1) 瀏覽器會解析三個東西

 

* 一個 HTML/SVG/XHTML,解析這三種文件會產生一個DOM Treehtml5

* CSS,解析CSS會產生CSS規則樹java

* JavaScript 腳本,主要是經過 DOM API 和 CSSOM API來操做 DOM Tree 和 CSS Rule Treenode

當瀏覽器得到一個HTML文件時,會自上而下加載,並在加載過程當中進行渲染。web

 

* 瀏覽器會將HTML解析成一個DOM樹,DOM的構建過程是一個深度遍歷的過程:當前節點的全部子節點都構建好後纔會去構建當前節點的下一個兄弟節點。後端

* 將CSS解析成 CSS Rule tree。瀏覽器

 

2) 解析完成後,瀏覽器引擎會經過 DOM Tree(構建DOM樹) 和CSS Rule Tree(css 渲染樹) 來構造 Rendering Tree(佈局渲染樹)。

 

 

 

注意: 

* Rendering Tree 渲染樹並不等同於 DOM Tree,由於一些像 Header 或 display:none 的東西就不必放在渲染樹中。

* CSS 的Rule Tree 主要是爲了完成匹配並把CSS Rule附加上 Rendering Tree 上的每一個 Element,也就是 DOM 節點,也就是所謂的 Frame。

* 有了Render Tree,瀏覽器已經能知道網頁中有哪些節點、各個節點的CSS定義以及它們的從屬關係。

* 而後,計算每一個 Frame(也就是每一個Element)的位置,這又叫 layout 和 reflow 過程。

3) 最後經過調用操做系統Native GUI的API 繪製   繪製

 

 

 

 

即遍歷render樹,並使用UI後端層繪製每一個節點

 

注:display:none 會觸發 reflow,而 visibility:hidden 只會觸發 repaint,由於沒有發現位置變化

 

 

 

 

注意 :佈局渲染樹中

重繪(repaint或redraw):當盒子的位置、大小以及其餘屬性,例如顏色、字體大小等都肯定下來以後,瀏覽器便把這些原色都按照各自的特性繪製一遍,將內容呈如今頁面上。

重繪是指一個元素外觀的改變所觸發的瀏覽器行爲,瀏覽器會根據元素的新屬性從新繪製,使元素呈現新的外觀。

觸發重繪的條件:改變元素外觀屬性。如:color,background-color等。

注意:table及其內部元素可能須要屢次計算才能肯定好其在渲染樹中節點的屬性值,比同等元素要多花兩倍時間,這就是咱們儘可能避免使用table佈局頁面的緣由之一。

重排(重構/迴流/reflow):當渲染樹中的一部分(或所有)由於元素的規模尺寸,佈局,隱藏等改變而須要從新構建, 這就稱爲迴流(reflow)。每一個頁面至少須要一次迴流,就是在頁面第一次加載的時候。

重繪和重排的關係:在迴流的時候,瀏覽器會使渲染樹中受到影響的部分失效,並從新構造這部分渲染樹,完成迴流後,瀏覽器會從新繪製受影響的部分到屏幕中,該過程稱爲重繪。

因此,重排一定會引起重繪,但重繪不必定會引起重排。

 

 

下面講下  css 匹配規則 如  #nav  li {},

CSS 匹配DOM Tree 主要是從右到左解析CSS 的 Selector。因此#nav li 咱們覺得這是一條很簡單的規則,很容易就能匹配到想要的元素,可是CSS會先去找全部的li 元素,而後再去肯定它的父元素是否是#nav。

在開始前,咱們必須瞭解一個真相:爲何排版引擎解析 CSS 選擇器時必定要從右往左析? 

 

1.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 的元素。

 

2.在創建 Render Tree 時(WebKit 中的「Attachment」過程),瀏覽器就要爲每一個 DOM Tree 中的元素根據 CSS 的解析結果(Style Rules)來肯定生成怎樣的 renderer。對於每一個 DOM 元素,必須在全部 Style Rules 中找到符合的 selector 並將對應的規則進行合併。選擇器的「解析」實際是在這裏執行的,在遍歷 DOM Tree 時,從 Style Rules 中去尋找對應的 selector。

 

3.由於全部樣式規則可能數量很大,並且絕大多數不會匹配到當前的 DOM 元素(由於數量很大因此通常會創建規則索引樹),因此有一個快速的方法來判斷「這個 selector 不匹配當前元素」就是極其重要的。

 

4.若是正向解析,例如「div div p em」,咱們首先就要檢查當前元素到 html 的整條路徑,找到最上層的 div,再往下找,若是遇到不匹配就必須回到最上層那個 div,往下再去匹配選擇器中的第一個 div,回溯若干次才能肯定匹配與否,效率很低。

 

5.逆向匹配則不一樣,若是當前的 DOM 元素是 div,而不是 selector 最後的 em,那隻要一步就能排除。只有在匹配時,纔會不斷向上找父節點進行驗證。

 

6.但由於匹配的狀況遠遠低於不匹配的狀況,因此逆向匹配帶來的優點是巨大的。同時咱們也可以看出,在選擇器結尾加上「*」就大大下降了這種優點,這也就是不少優化原則提到的儘可能避免在選擇器末尾添加通配符的緣由。

 

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

 

 

http://stevesouders.com/efws/css-selectors/baseline.php  css選擇器測試

致使重排 迴流 reflow

clientWidth、clientHeight、clientTop、clientLeft
offsetWidth、offsetHeight、offsetTop、offsetLeft
scrollWidth、scrollHeight、scrollTop、scrollLeft
scrollIntoView()、scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()

還有display:none 到block

 

css 分層展現

這是由 z-index CSS 屬性指定的。它表明了框的第三個維度,也就是沿「z 軸」方向的位置。

這些框分散到多個堆棧(稱爲堆棧上下文)中。在每個堆棧中,會首先繪製後面的元素,而後在頂部繪製前面的元素,以便更靠近用戶。若是出現重疊,新繪製的元素就會覆蓋以前的元素。 
堆棧是按照 z-index 屬性進行排序的。具備「z-index」屬性的框造成了本地堆棧。視口具備外部堆棧。

<style type="text/css">
      div {
        position: absolute;
        left: 2in;
        top: 2in;
      }
</style>

<p>
    <div
         style="z-index: 3;background-color:red; width: 1in; height: 1in; ">
    </div>
    <div
         style="z-index: 1;background-color:green;width: 2in; height: 2in;">
    </div>
 </p>

  

 

 

 

1. 用戶輸入網址(假設是個html頁面,而且是第一次訪問),瀏覽器向服務器發出請求,服務器返回html文件; 
2. 瀏覽器開始載入html代碼,發現<head>標籤內有一個<link>標籤引用外部CSS文件; 
3. 瀏覽器又發出CSS文件的請求,服務器返回這個CSS文件; 
4. 瀏覽器繼續載入html中<body>部分的代碼,而且CSS文件已經拿到手了,能夠開始渲染頁面了; 
5. 瀏覽器在代碼中發現一個<img>標籤引用了一張圖片,向服務器發出請求。此時瀏覽器不會等到圖片下載完,而是繼續渲染後面的代碼; 
6. 服務器返回圖片文件,因爲圖片佔用了必定面積,影響了後面段落的排布,所以瀏覽器須要回過頭來從新渲染這部分代碼; 
7. 瀏覽器發現了一個包含一行Javascript代碼的<script>標籤,趕快運行它; 
8. Javascript腳本執行了這條語句,它命令瀏覽器隱藏掉代碼中的某個<div> (style.display=」none」)。忽然少了這麼一個元素,瀏覽器不得不從新渲染這部分代碼; 
9. 終於等到了</html>的到來,瀏覽器淚流滿面…… 
10. 等等,還沒完,用戶點了一下界面中的「換膚」按鈕,Javascript讓瀏覽器換了一下<link>標籤的CSS路徑; 
11. 瀏覽器召集了在座的各位<div><span><ul><li>們,「大夥兒收拾收拾行李,咱得從新來過……」,瀏覽器向服務器請求了新的CSS文件,從新渲染頁面。

參考

https://www.cnblogs.com/yc-755909659/p/6599553.html

How Browsers Work 這篇文章

瀏覽器的工做原理:現代網絡瀏覽器幕後揭祕 - HTML5 Rockswww.html5rocks.com

相關文章
相關標籤/搜索