在搞清楚回流和重繪的概念之前,我們要清除瀏覽器的渲染過程。
- 解析生成DOM Tree(此時包含所有節點,包括display:none);
- 根據CSS Object Module(CCSSOM)計算節點的幾何屬性(坐標和大小)(margin,pading,height,width等),生成Render Tree(不包含display: none的節點);這一過程叫回流或者布局;
-
在Render Tree進一步渲染其它屬性。如:color等。
重繪:當我們對 DOM 的修改導致了樣式的變化、卻並未影響其幾何屬性(比如修改了顏色或背景色)時,瀏覽器不需重新計算元素的幾何屬性、直接為該元素繪制新的樣式(跳過了上圖所示的回流環節)。
回流:當我們對 DOM 的修改引發了 DOM 幾何尺寸的變化(比如修改元素的寬、高或隱藏元素等)時,瀏覽器需要重新計算元素的幾何屬性(其他元素的幾何屬性和位置也會因此受到影響),然后再將計算的結果繪制出來。這個過程就是回流(也叫重排)
通過上訴我們知道:回流必定引發重繪,重繪不一定引發回流。回流的代價比重繪高。
1)搞清楚了回流和重繪的概念,我們很容易知道哪些屬性的修改會引起回流:
- DOM的添加和刪除;
- 頁面的加載;
- 元素尺寸改變——邊距、填充、邊框、寬度和高度;
- 元素位置的改變;
- 內容變化,比如用戶在input框中輸入文字;
- 瀏覽器窗口尺寸改變——resize事件發生時;
-
獲取某些屬性:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、 clientTop、clientLeft、clientWidth、clientHeight。(瀏覽器為了返回最精確的值,需要flush隊列,因為隊列中可能會有影響到這些值的操作)
2)常見引起重繪的屬性:
3)如何減少回流、重繪:
- 使用 transform 替代 top
- 使用 visibility 替換 display: none ,因為前者只會引起重繪,后者會引發回流(改變了布局)
- 不要把節點的屬性值放在一個循環里當成循環里的變量。
- 不要使用 table 布局,可能很小的一個小改動會造成整個 table 的重新布局
- 動畫實現的速度的選擇,動畫速度越快,回流次數越多,也可以選擇使用 requestAnimationFrame
- CSS 選擇符從右往左匹配查找,避免節點層級過多
-
將頻繁重繪或者回流的節點設置為圖層,圖層能夠阻止該節點的渲染行為影響別的節點。比如對於 video 標簽來說,瀏覽器會自動將該節點變為圖層。
瀏覽器的回流優化機制:瀏覽器會維護1個隊列,把所有會引起重排、重繪的操作放入這個隊列,等隊列中的操作到了一定的數量或者到了一定的時間間隔,瀏覽器就會flush隊列,進行一個批處理。這樣就會讓多次的重排、重繪變成一次重排重繪。
參考文章:
前端開發這么多年,你真的了解瀏覽器頁面渲染機制嗎? | 技術頭條