css 頁面重繪和回流(重排)以及優化
一、html頁面的呈現流程
1. 瀏覽器把獲取到的HTML代碼解析成1個DOM樹,HTML中的每個tag都是DOM樹中的1個節點,根節點就是我們常用的document對象。DOM樹裏包含了所有HTML標簽,包括display:none隱藏,還有用JS動態添加的元素等。
2. 瀏覽器把所有樣式(用戶定義的CSS和用戶代理)解析成樣式結構體,在解析的過程中會去掉瀏覽器不能識別的樣式,比如IE會去掉-moz開頭的樣式,而FF會去掉_開頭的樣式。
3、DOM Tree 和樣式結構體組合後構建render tree, render tree類似於DOM tree,但區別很大,render tree能識別樣式,render tree中每個NODE都有自己的style,而且 render tree不包含隱藏的節點 (比如display:none的節點,還有head節點),因為這些節點不會用於呈現,而且不會影響呈現的,所以就不會包含到 render tree中。註意 visibility:hidden隱藏的元素還是會包含到 render tree中的,因為visibility:hidden 會影響布局(layout),會占有空間。根據CSS2的標準,render tree中的每個節點都稱為Box (Box dimensions),理解頁面元素為一個具有填充、邊距、邊框和位置的盒子。
4. 一旦render tree構建完畢後,瀏覽器就可以根據render tree來繪制頁面了。
二、回流與重繪
1. 當render tree中的一部分(或全部)因為元素的規模尺寸,布局,隱藏等改變而需要重新構建。這就稱為回流(reflow)。每個頁面至少需要一次回流,就是在頁面第一次加載的時候。在回流的時候,瀏覽器會使渲染樹中受到影響的部分失效,並重新構造這部分渲染樹,完成回流後,瀏覽器會重新繪制受影響的部分到屏幕中,該過程成為重繪。
2. 當render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響布局的,比如background-color。則就叫稱為重繪。
註意:回流必將引起重繪,而重繪不一定會引起回流。
回流何時發生:
當頁面布局和幾何屬性改變時就需要回流。下述情況會發生瀏覽器回流:
1、添加或者刪除可見的DOM元素;
2、元素位置改變;
3、元素尺寸改變——邊距、填充、邊框、寬度和高度
4、內容改變——比如文本改變或者圖片大小改變而引起的計算值寬度和高度改變;
5、頁面渲染初始化;
6、瀏覽器窗口尺寸改變——resize事件發生時;
三、優化(減少回流、重繪)
瀏覽器本身的優化策略:瀏覽器會維護1個隊列,把所有會引起回流、重繪的操作放入這個隊列,等隊列中的操作到了一定的數量或者到了一定的時間間隔,瀏覽器就會flush隊列,進行一個批處理。這樣就會讓多次的回流、重繪變成一次回流重繪。但有時候我們寫的一些代碼可能會強制瀏覽器提前flush隊列,這樣瀏覽器的優化可能就起不到作用了。當你請求向瀏覽器請求一些 style信息的時候,就會讓瀏覽器flush隊列。
減少對render tree的操作(合並多次多DOM和樣式的修改),並減少對一些style信息的請求,盡量利用好瀏覽器的優化策略
方法:
1. 將多次改變樣式屬性的操作合並成一次操作。
2.將需要多次重排的元素,position屬性設為absolute或fixed,這樣此元素就脫離了文檔流,它的變化不會影響到其他元素。例如有動畫效果的元素就最好設置為絕對定位。
3. 在內存中多次操作節點,完成後再添加到文檔中去。例如要異步獲取表格數據,渲染到頁面。可以先取得數據後在內存中構建整個表格的html片段,再一次性添加到文檔中去,而不是循環添加每一行。
4. 由於display屬性為none的元素不在渲染樹中,對隱藏的元素操作不會引發其他元素的重排。如果要對一個元素進行復雜的操作時,可以先隱藏它,操作完成後再顯示。這樣只在隱藏和顯示時觸發2次重排。
5. 在需要經常取那些引起瀏覽器重排的屬性值時,要緩存到變量。
css 頁面重繪和回流(重排)以及優化