HTML 經過解析生成 DOM樹; CSS經過解析生成 Style Rules。 二者一結合生成了Render Tree。 通過layout計算出DOM要顯示的寬高、位置、顏色。 最后渲染在界面上,用戶就看到了。
瀏覽器的渲染過程:
- 解析 HTML 構建 DOM(DOM 樹),並行請求 css/image/js
- CSS 文件下載完成,開始構建 CSSOM(CSS 樹)
- CSSOM 構建結束后,和 DOM 一起生成 Render Tree(渲染樹)
- 布局(Layout):計算出每個節點在屏幕中的位置
- 顯示(Painting):通過顯卡把頁面畫到屏幕上
DOM 樹 和 渲染樹 的區別:
- DOM 樹與 HTML 標簽一一對應,包括 head 和隱藏元素
- 渲染樹不包括 head 和隱藏元素,大段文本的每一個行都是獨立節點,每一個節點都有對應的 css 屬性
CSS會阻塞DOM解析嗎?
對於一個HTML文檔來說,不管是內聯還是外鏈的css,都會阻礙后續的dom渲染,但是不會阻礙后續dom的解析。
當css文件放在中時,雖然css解析也會阻塞后續dom的渲染,但是在解析css的同時也在解析dom,所以等到css解析完畢就會逐步的渲染頁面了。
重繪和回流(重排)的區別和關系?
- 重繪:當渲染樹中的元素外觀(如:顏色)發生改變,不影響布局時,產生重繪
- 回流:當渲染樹中的元素的布局(如:尺寸、位置、隱藏/狀態狀態)發生改變時,產生重繪回流
- 注意:JS 獲取 Layout 屬性值(如:offsetLeft、scrollTop、getComputedStyle 等)也會引起回流。因為瀏覽器需要通過回流計算最新值
- 回流必將引起重繪,而重繪不一定會引起回流
DOM結構中的各元素都有自己的盒子,這些都需要瀏覽器根據各種樣式來計算並更具結果將元素放到它該出現的位置,這個過程叫 reflow
觸發reflow:
- 添加或刪除可見的DOM元素。
- 元素位置改變。
- 元素的尺寸改變(包括:內外邊距、邊框厚度、寬度、高度等屬性的改變)。
- 內容改變。
- 頁面渲染器初始化。
- 瀏覽器窗口尺寸改變。
如何最小化重繪(repaint)和回流(reflow)?
- 需要要對DOM元素進行復雜的操作時,可以先隱藏(display:"none"),操作完成后再顯示
- 需要創建多個 DOM 節點時,使用 DocumentFragment 創建完后一次性的加入 document,或使用字符串拼接方式構建好對應HTML后再使用innerHTML來修改頁面
- 緩存 Layout 屬性值,如:var left = elem.offsetLeft; 這樣,多次使用 left 只產生一次回流
- 避免用 table 布局(table 元素一旦觸發回流就會導致 table 里所有的其它元素回流)
- 避免使用 css 表達式(expression),因為每次調用都會重新計算值(包括加載頁面)
- 盡量使用 css 屬性簡寫,如:用 border 代替 border-width, border-style, border-color
- 批量修改元素樣式:elem.className 和 elem.style.cssText 代替 elem.style.xxx