(個人blog遷移文章。)
前言:
頁面設計中,不可避免的需要瀏覽器進行repaint和reflow。那到底什么是repaint和reflow呢。下面談談自己對repaint和reflow的理解,以及結合其他技術牛的講解,談談如何優化repaint和reflow。
初步介紹:
開發一個頁面時,不可避免的需要進行repaint和reflow。也就只有古來的靜態頁面才會不存在repaint和reflow。repaint主要是針對某一個DOM元素進行的重繪,reflow則是回流,針對整個頁面的重排。字面意思來說:repaint就是重繪,reflow就是回流。repaint和reflow的目的是:展示一個新的頁面樣貌。
嚴重性:
在性能優先的前提下,性能消耗 reflow大於repaint。
體現:
repaint是某個DOM元素進行重繪;reflow是整個頁面進行重排,也就是頁面所有DOM元素渲染。
如何觸發:
style變動造成repaint和reflow。
不涉及任何DOM元素的排版問題的變動為repaint,例如元素的color/text-align/text-decoration等等屬性的變動。
除上面所提到的DOM元素style的修改基本為reflow。例如元素的任何涉及長、寬、行高、邊框、display等style的修改。
常見觸發場景:
- 觸發repaint:
- color的修改,如color=#ddd;
- text-align的修改,如text-align=center;
- a:hover也會造成重繪。
- :hover引起的顏色等不導致頁面回流的style變動。
- 等等太多,一時間寫出來也太難想了。
- 觸發reflow:
- width/height/border/margin/padding的修改,如width=778px;
- 動畫,:hover等偽類引起的元素表現改動,display=none等造成頁面回流;
- appendChild等DOM元素操作;
- font類style的修改;
- background的修改,注意着字面上可能以為是重繪,但是瀏覽器確實回流了,經過瀏覽器廠家的優化,部分background的修改只觸發repaint,當然IE不用考慮;
- scroll頁面,這個不可避免;
- resize頁面,桌面版本的進行瀏覽器大小的縮放,移動端的話,還沒玩過能拖動程序,resize程序窗口大小的多窗口操作系統。
- 讀取元素的屬性(這個無法理解,但是技術達人是這么說的,那就把它當做定理吧):讀取元素的某些屬性(offsetLeft、offsetTop、offsetHeight、offsetWidth、scrollTop/Left/Width/Height、clientTop/Left/Width/Height、getComputedStyle()、currentStyle(in IE));
如何避免:
說避免那是不可能的,不然就是以前古老的靜態頁面了,沒有交互,那在現在看來,就是一個失敗的作品。所以,在我們進行網頁設計的時候,就必須盡量減少頁面的repaint和reflow。repaint和reflow的目的是為了展示一個新的頁面,那么我們在進行頁面交互時,盡量通過各種方法減少repaint和reflow但又能展示一個新的頁面的目的。所以下面將結合其他技術達人的建議,通過自己的理解,給大家講解如何避免和優化repaint和reflow:
下面是大神Nicole Sullivan的原話:
- Change classes on the element you wish to style (as low in the dom tree as possible)
- Avoid setting multiple inline styles
- Apply animations to elements that are position fixed or absolute
- Trade smoothness for speed
- Avoid tables for layout
- Avoid JavaScript expressions in the CSS (IE only)
- 盡可能在DOM末梢通過改變class來修改元素的style屬性:盡可能的減少受影響的DOM元素。
- 避免設置多項內聯樣式:使用常用的class的方式進行設置樣式,以避免設置樣式時訪問DOM的低效率。
- 設置動畫元素position屬性為fixed或者absolute:由於當前元素從DOM流中獨立出來,因此受影響的只有當前元素,元素repaint。
- 犧牲平滑度滿足性能:動畫精度太強,會造成更多次的repaint/reflow,犧牲精度,能滿足性能的損耗,獲取性能和平滑度的平衡。
- 避免使用table進行布局:table的每個元素的大小以及內容的改動,都會導致整個table進行重新計算,造成大幅度的repaint或者reflow。改用div則可以進行針對性的repaint和避免不必要的reflow。
- 避免在CSS中使用運算式:學習CSS的時候就知道,這個應該避免,不應該加深到這一層再去了解,因為這個的后果確實非常嚴重,一旦存在動畫性的repaint/reflow,那么每一幀動畫都會進行計算,性能消耗不容小覷。
參考文獻:
- 頁面重構應注意的repaint和reflow
- 如何減少瀏覽器repaint和reflow(上)
- 回流與重繪:CSS性能讓JavaScript變慢?
- Reflows & Repaints: CSS Performance making your JavaScript slow?
覺得有用,點個贊,贊贊更健康。