在實習做一個移動項目的時候,實現一個動畫效果,在 iPhone 和 Chrome 上調試沒有問題,在千元左右的 Android 機上測試問題就很大了,卡頓非常明顯,百思不得其解,吐血,卒。
這個悲傷的故事就是本文的引子,真真切切的體會到了 CSS 對使用者體驗的影響非常明顯,稍有不慎就是一個大坑。下面,我們就來談談 CSS 效能最佳化的問題。
載入效能
減少檔案體積,壓縮代碼
減少阻塞載入,不要用 import
提高並發(這個不甚理解)
選取器效能
對整體效能的影響可以忽略不計了,但是選取器的考究更多是為了正常化和可維護性、健壯性。具體怎麼實施可以參考 Github 的這個分享:GitHub's CSS Performance by Jon Rohan
渲染效能
渲染效能是 CSS 最佳化最重要的關注對象。我們先來瞭解一下瀏覽器的渲染機制。
瀏覽器的渲染機制
瀏覽器渲染展示網頁的過程,大致分為以下幾個步驟:
1.解析HTML(HTML Parser)
2.構建DOM樹(DOM Tree)
3.渲染樹構建(Render Tree)
4.繪製渲染樹(Painting)
謹慎選擇高消耗的樣式
什麼 CSS 屬性是高消耗的?就是那些繪製前需要瀏覽器進行大量計算的屬性。
box-shadows
border-radius
transparency
transforms
CSS filters(效能殺手)
避免過分重排(Reflow)
簡單解釋一下 Reflow:當元素改變的時候,將會影響文檔內容或結構,或元素位置,此過程稱為 Reflow。
怎麼減少 Reflow
1.不要一條一條地修改 DOM 的樣式,預先定義好 class,然後修改 DOM 的 className
2.把 DOM 離線後修改,比如:先把 DOM 給 display:none (有一次 Reflow),然後你修改100次,然後再把它顯示出來
3.不要把 DOM 結點的屬性值放在一個迴圈裡當成迴圈裡的變數
4.儘可能不要修改影響範圍比較大的 DOM
5.為動畫的元素使用絕對位置 absolute / fixed
6.不要使用 table 布局,可能很小的一個小改動會造成整個 table 的重新布局
避免過分重繪(Repaints)
當元素改變的時候,將不會影響元素在頁面當中的位置(比如 background-color, border-color, visibility),瀏覽器僅僅會應用新的樣式重繪此元素,此過程稱為 Repaint。
最佳化動畫
CSS3 動畫是最佳化的重中之重。除了做到上面兩點,減少 Reflow 和 Repaints 之外,還需要注意以下方面。
啟用 GPU 硬體加速
GPU(Graphics Processing Unit) 是影像處理器。GPU 硬體加速是指應用 GPU 的圖形效能對瀏覽器中的一些圖形操作交給 GPU 來完成,因為 GPU 是專門為處理圖形而設計,所以它在速度和能耗上更有效率。
GPU 加速可以不僅應用於3D,而且也可以應用於2D。這裡, GPU 加速通常包括以下幾個部分:Canvas2D,布局合成(Layout Compositing), CSS3轉換(transitions),CSS3 3D變換(transforms),WebGL和視頻(video)。
/* * 根據上面的結論 * 將 2d transform 換成 3d * 就可以強制開啟 GPU 加速 * 提高動畫效能 */div { transform: translate(10px, 10px);}div { transform: translate3d(10px, 10px, 0);}
需要注意的是,開啟硬體加速相應的也會有額外的開銷,參見這篇文章 CSS 硬體加速的好與壞