CSS 前端頁面渲染優化 屬性 will-change

Hanyuxi發表於2020-04-01

前言

  • 當觸發scroll、resize這類的滾動事件時,被觸發的頻率非常高,間隔也特別近。如果事件中涉及到大量的位置計算、DOM操作、元素重繪等工作,並且這些工作無法在下一個scroll事件出發前完成,就會造成瀏覽器掉幀(掉幀就是例如影像一閃一閃的,運動不流暢的情況)。加之使用者滑鼠滾動往往是連續的,就會持續觸發scroll事件導致掉幀擴大、瀏覽器CPU使用率增加,使用者體驗收到影響。

  • 而CSS屬性will-change為web開發者提供了一種告知瀏覽器該元素會有哪些變化的方法,這樣瀏覽器就可以在元素屬性真正發生變化之前提前做好對應的優化準備工作。這種優化可以將一部分複雜的計算工作提前準備好,使頁面的反應更為快速靈敏。

準備知識

CPU

CPU即中央處理器,它的功能主要是解釋計算機指令以及處理計算機軟體中的資料,也被稱為主機板。

GPU

GPU是圖形處理器,專門處理和繪製圖形相關的硬體。GPU是專為執行復雜的數學和幾何計算而設計的,使得CPU從圖形處理的任務中解放出來,可以執行其他更多的系統任務。

硬體加速

  • 硬體加速意味著Graphics Processing Unit(GPU)會通過代替Central Processing Unit (CPU)做一些負荷比較大的事情,來協助瀏覽器快速渲染頁面,當CSS操作使用硬體加速的時候,通常會使頁面渲染速度加快。

  • 瀏覽器渲染頁面的過程:

    1.解析HTML(HTML Parser)

    2.構建DOM樹(DOM Tree)

    3.渲染樹構建(Render Tree)

    4.繪製渲染樹(Painting)

    簡單的解釋就是:瀏覽器通過請求得到伺服器返回的html,因為html是樹狀結構,通過瀏覽器解析生成DOM Tree。在CSS解析完畢後,將得到的模擬樹CSSOM Tree和DOM Tree結合構建Render Tree,最終用來進行繪圖(Painting)

CSS  前端頁面渲染優化 屬性 will-change

CSS的動畫、變形、漸變並不會自動觸發GPU加速,而是使用瀏覽器稍慢的軟體渲染引擎。在transition、transform和animation的世界裡,應該解除安裝程式到GPU以加速速度。只有3D變形會有自己的layer,而2D變形則不會。

will-change

1.will-change 是什麼?

will-change的功能是:提前通知瀏覽器元素將要做什麼動畫,讓瀏覽器提前準備合適的優化設定

官方文件說:這是一個仍處於試驗階段的功能,所以在未來版本的瀏覽器中該語法的功能和行為kennel隨之變化。

CSS3 will-change屬於web標準屬性,相容性這塊Chrome/FireFox/Opera都是支援的。

CSS  前端頁面渲染優化 屬性 will-change
注意:will-change真正的行為觸發之前會告訴瀏覽器:“我要觸發啦”。這意味著不是通過一個3D變換迫使我們轉換到GPU,而是我們現在可以使用一個專用的屬性來通知瀏覽器留意接下來的變化,從而優化和分配記憶體。提前預約從容不迫。

2.語法

will-change: auto
will-change: scroll-position
will-change: contents
will-change: transform        // Example of <custom-ident> 
will-change: opacity          // Example of <custom-ident>
will-change: left, top        // Example of two <animateable-feature>

will-change: unset
will-change: initial
will-change: inherit
複製程式碼

auto

表示沒有特別指定哪些屬性會變化,需要瀏覽器自己去猜,然後使用瀏覽器經常使用的一些常規方法進行優化。

可以是以下值:

scroll-position

表示開發者希望在不久後改變滾動條的位置或者使之產生動畫

contents

表示開發者希望在不久後改變元素內容中的某些東西,或者使它們產生動畫

表示開發者希望在不久後改變指定的屬性名或者使之產生動畫。如果屬性名是簡寫,則代表所有與之對應的簡寫或者全寫的屬性

will-change的使用

hover使用

不要直接寫在預設狀態中,因為will-change會一直掛載


.will-change {
  will-change: transform;
  transition: transform 0.3s;
}
.will-change:hover {
  transform: scale(1.5);
}
複製程式碼

可以讓父元素hover的時候,宣告will-change,這樣移出的時候就會自動remove,觸發的範圍基本上是有效元素範圍。


.will-change-parent:hover .will-change {
  will-change: transform;
}
.will-change {
  transition: transform 0.3s;
}
.will-change:hover {
  transform: scale(1.5);
}
複製程式碼

JS使用

var el = document.getElementById('element');

// 當滑鼠移動到該元素上時給該元素設定 will-change 屬性
el.addEventListener('mouseenter', hintBrowser);
// 當 CSS 動畫結束後清除 will-change 屬性
el.addEventListener('animationEnd', removeHint);

function hintBrowser() {
  // 填寫上那些你知道的,會在 CSS 動畫中發生改變的 CSS 屬性名們
  this.style.willChange = 'transform, opacity';
}

function removeHint() {
  this.style.willChange = 'auto';
}
複製程式碼

如果某個應用在按下鍵盤的時候會翻頁,比如相簿或者幻燈片一類的,它的頁面很大很複雜,此時在樣式表中寫上 will-change 是合適的。這會使瀏覽器提前準備好過渡動畫,當鍵盤按下的時候就能立即看到靈活輕快的動畫。

.slide {
  will-change: transform;
}
複製程式碼

使用will-change的注意事項

不要將 will-change應用到太多元素上:

瀏覽器已經盡力嘗試去優化一切可以優化的東西了。有一些更強力的優化,如果與 will-change 結合在一起的話,有可能會消耗很多機器資源,如果過度使用的話,可能導致頁面響應緩慢或者消耗非常多的資源。

有節制地使用:

通常,當元素恢復到初始狀態時,瀏覽器會丟棄掉之前做的優化工作。但是如果直接在樣式表中顯式宣告瞭 will-change 屬性,則表示目標元素可能會經常變化,瀏覽器會將優化工作儲存得比之前更久。所以最佳實踐是當元素變化之前和之後通過指令碼來切換 will-change 的值。

不要過早應用 will-change優化:

如果你的頁面在效能方面沒什麼問題,則不要新增 will-change 屬性來榨取一丁點的速度。 will-change 的設計初衷是作為最後的優化手段,用來嘗試解決現有的效能問題。它不應該被用來預防效能問題。過度使用 will-change 會導致大量的記憶體佔用,並會導致更復雜的渲染過程,因為瀏覽器會試圖準備可能存在的變化過程。這會導致更嚴重的效能問題。

給它足夠的工作時間:

這個屬性是用來讓頁面開發者告知瀏覽器哪些屬性可能會變化的。然後瀏覽器可以選擇在變化發生前提前去做一些優化工作。所以給瀏覽器一點時間去真正做這些優化工作是非常重要的。使用時需要嘗試去找到一些方法提前一定時間獲知元素可能發生的變化,然後為它加上 will-change 屬性。

相關文章