Web 效能優化-CSS3 硬體加速(GPU 加速)
CSS3 硬體加速又叫做 GPU 加速,是利用 GPU 進行渲染,減少 CPU 操作的一種優化方案。由於 GPU 中的 transform 等 CSS 屬性不會觸發 repaint,所以能大大提高網頁的效能。
動畫與幀
瀏覽器中動畫也是由一幀一幀的圖片組成的。我們首先看一下,瀏覽器每一幀都做了什麼。
- JavaScript:JavaScript 實現動畫效果,DOM 元素操作等。
- Style(計算樣式):確定每個 DOM 元素應該應用什麼 CSS 規則。
- Layout(佈局):計算每個 DOM 元素在最終螢幕上顯示的大小和位置。由於 web 頁面的元素佈局是相對的,所以其中任意一個元素的位置發生變化,都會聯動的引起其他元素髮生變化,這個過程叫 reflow。
- Paint(繪製):在多個層上繪製 DOM 元素的的文字、顏色、影象、邊框和陰影等。
- Composite(渲染層合併):按照合理的順序合併圖層然後顯示到螢幕上。
動畫與圖層
瀏覽器在獲取 render tree(詳細知識可以檢視Web效能優化-頁面重繪和迴流(重排))後,渲染樹中包含了大量的渲染元素,每一個渲染元素會被分到一個圖層中,每個圖層又會被載入到 GPU 形成渲染紋理。GPU 中 transform 是不會觸發 repaint 的,這一點非常類似 3D 繪圖功能,最終這些使用 transform 的圖層都會由獨立的合成器程序進行處理。
過程如下:
render tree -> 渲染元素 -> 圖層 -> GPU 渲染 -> 瀏覽器複合圖層 -> 生成最終的螢幕影象。
chrome devtools 中可以開啟 Rendering 中的 Layer borders 檢視圖層紋理。
其中黃色邊框表示該元素有 3d 變換,表示放到一個新的複合層(composited layer)中渲染,藍色柵格表示正常的 render layer。
在 GPU 渲染的過程中,一些元素會因為符合了某些規則,而被提升為獨立的層(黃色邊框部分),一旦獨立出來,就不會影響其它 DOM 的佈局,所以我們可以利用這些規則,將經常變換的 DOM 主動提升到獨立的層,那麼在瀏覽器的一幀執行中,就可以減少 Layout 和 Paint 的時間了。
建立獨立圖層
哪些規則能讓瀏覽器主動幫我們建立獨立的層呢?
- 3D 或者透視變換(perspective,transform) 的 CSS 屬性。
- 使用加速視訊解碼的 video 元素。
- 擁有 3D(WebGL) 上下文或者加速 2D 上下文的 canvas 元素。
- 混合外掛(Flash)。
- 對自己的 opacity 做 CSS 動畫或使用一個動畫 webkit 變換的元素。
- 擁有加速 CSS 過濾器的元素。
- 元素有一個包含複合層的後代節點(換句話說,就是一個元素擁有一個子元素,該子元素在自己的層裡)。
- 元素有一個兄弟元素在複合圖層渲染,並且該兄弟元素的 z-index 較小,那這個元素也會被應用到複合圖層。
關於 z-index 導致的硬體加速的問題,可以檢視這篇文章CSS3硬體加速也有坑!!
開啟 GPU 加速
CSS 中的以下幾個屬效能觸發硬體加速:
- transform
- opacity
- filter
- will-change
如果有一些元素不需要用到上述屬性,但是需要觸發硬體加速效果,可以使用一些小技巧來誘導瀏覽器開啟硬體加速。
.element { -webkit-transform: translateZ(0); -moz-transform: translateZ(0); -ms-transform: translateZ(0); -o-transform: translateZ(0); transform: translateZ(0); /**或者**/ transform: rotateZ(360deg); transform: translate3d(0, 0, 0); }
注意:我在不同的資料中查到的 transform 是否能觸發硬體加速的結果不同,自己測試後,發現結果是可以。
要注意的問題
(1)過多地開啟硬體加速可能會耗費較多的記憶體,因此什麼時候開啟硬體加速,給多少元素開啟硬體加速,需要用測試結果說話。
(2)GPU 渲染會影響字型的抗鋸齒效果。這是因為 GPU 和 CPU 具有不同的渲染機制,即使最終硬體加速停止了,文字還是會在動畫期間顯示得很模糊。