CSS will-change 屬性

介紹

若是你注意到在webkit的瀏覽器上「flicker」一些CSS操做(尤爲是變形和動畫方面的)的表現,你極可能以前就注意過硬件加速
css

CPU、GPU和硬件加速

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

顧名思義,CPU和GPU都是計算機處理單元。CPU在電腦主板,幾乎處理電腦的一切操做,有電腦大腦之稱;GPU在顯卡上,負責處理和渲染圖形。此外GPU經過特殊的設計,使其擅長於渲染圖形所需的數學和幾何運算。所以把操做轉嫁到GPU能夠得到顯著的性能提高,同時也能夠減小移動設備CPU的爭用。html5

硬件加速(或者說GPU加速)依賴於瀏覽器渲染頁面使用的layering model,當特定的操做(CSS 3D變形)做用於頁面上的一個元素,元素移動到它本身的layer,在這個layer中元素合一不受頁面其餘元素的干擾獨立渲染,而後複合到頁面中去。在這種隔離內容渲染的工做方式下,若是頁面的變化僅僅是該元素的變形,其他部分沒必要被從新渲染,這會帶來顯著的速度優點。值得注意的是只有3D變形會有本身的layer,2D變形不會。git

CSS的動畫、變形、漸變並不會自動的觸發GPU加速,而是使用瀏覽器稍慢的軟件渲染引擎。然而一些瀏覽器提供了hardware acceleration by means of certain properties來獲取更高的渲染性能。 舉個例子,opacity屬性是幾個可以加速的屬性之一,由於GPU能夠方便的處理。基本上任何層的透明度漸變瀏覽器都會交給GPU處理來加速。除了opacity可以使用GPU處理的就是CSS 3D變形了github

translateZ() (or translate3d()) Hack

很長一段時間內咱們都經過translateZ()或者translate3d() hack來騙取瀏覽器觸發硬件加速,具體作法就是爲元素添加沒有變化的3D變形,好比元素在2維空間能夠經過添加如下CSS來硬件加速web

transform: translate3d(0, 0, 0); 複製代碼

所謂硬件加速就是建立了一個被傳遞到GPU處理的層的操做,然而強制使用hack方式建立layer並非長久之計,建立layer的技術可使頁面加速,可是也有代價:它們佔用RAM和GPU存儲空間(考慮到移動設備的存儲容量有限),因此必須唄當心使用,確保這麼作真的對頁面渲染有所幫助瀏覽器

爲了不建立layer的hacks,一個容許咱們提早通知瀏覽器咱們將對元素作何種變化的CSS屬性被引入,這樣瀏覽器能夠優化處理元素渲染的方式,爲元素提早準備昂貴的動畫處理操做,這就是wiil-change屬性app

牛逼的 will-change屬性

will-change屬性能夠提早通知瀏覽器咱們要對元素作什麼動畫,這樣瀏覽器能夠提早準備合適的優化設置。這樣能夠避免對頁面響應速度有重要影響的昂貴成本。元素能夠更快的被改變,渲染的也更快,這樣頁面能夠快速更新,表現的更加流暢。post

舉個例子,當對於素使用 CSS 3D變形時,元素及其內容能夠在合成到頁面以前被建立到咱們以前說的layer。然而把元素放到layer中是個昂貴的操做,這將會致使變形動畫延遲一個課件的瞬間,也就是flicker性能

爲了不這種延時,咱們能夠在發生以前通知瀏覽器,這樣瀏覽器會有必定的時間去準備這些變化,當發生的時候layer已經準備好了,這樣動畫酒會很流暢,不會閃屏

使用will-change提示瀏覽器關於即將發生的變形十分簡單,添加個CSS屬性就行

will-change: transform; 複製代碼

也能夠告訴瀏覽器要改變元素的滾動條位置,或者多個要變化的屬性,寫下屬性的名字就行,也能夠寫多個,逗號隔開

will-change: transform, opacity; 複製代碼

聲明瞭元素即將進行的變化會讓瀏覽器在渲染頁面時作更好的決定,這明顯比以前說的3D hacks要好。

合理使用

瞭解了will-change的行爲,爲瀏覽器上一切元素設置will-change是否是效率會變高?答案是否認的,will-change若是被濫用會使頁面崩潰。

will-change也有反作用,雖然並不直接可見,畢竟它只是在背後和瀏覽器說悄悄話,爲了合理使用will-change,給一些小建議

不要聲明太多屬性或爲太多元素聲明

*,
*::before, *::after { will-change: all; } 複製代碼

雖然看起來很屌,但其實對頁面渲染傷害很大,這樣的規則設了和沒設沒什麼區別,瀏覽器原本就嘗試最優的渲染全部元素,就等於你讓老師重點照顧班裏每一個同窗同樣,就是廢話!

其實這甚至是有害的,由於一些操做會佔用太多的資源,甚至會致使頁面奔潰,就等於強制要求老師爲每一個學生補課,累死了。。。

給瀏覽器足夠的時間工做

will-change顧名思義,通知瀏覽器即將發生的變化,而不是正在發生的變化。使用will-change,咱們要求瀏覽器重點照顧咱們聲明的元素,爲了這個瀏覽器須要必定的時間來組織優化操做,這樣當變化發生的時候,優化才能沒有延遲的做用到元素

在變化前當即爲元素添加will-change幾乎沒有做用,可能還不如不設置,由於會致使新的layer建立

.element:hover { will-change: transform; transition: transform 2s; transform: rotate(30deg) scale(1.5); } 複製代碼

這樣的設置就沒什麼用,咱們須要給瀏覽器足夠的時間,下面這樣就是有用的,感覺一下

.element { /* style rules */ transition: transform 1s ease-out; } .element:hover { will-change: transform; } .element:active { transform: rotateY(180deg); } 複製代碼

若是必定要hover的時候,也有技巧

.element { transition: opacity .3s linear; } /* declare changes on the element when the mouse enters / hovers its ancestor */ .ancestor:hover .element { will-change: opacity; } /* apply change when element is hovered */ .element:hover { opacity: .5; } 複製代碼

其實核心思想就是讓瀏覽器有時間去準備

變化完成後移除will-change

對於通常的優化,當變化完成的時候瀏覽器會撤銷優化,恢復普通模式,可是若是使用了will-change會致使該優化遲遲不能釋放,這就要求咱們用完了就釋放

這時候咱們須要藉助JavaScript

// Rough generic example // Get the element that is going to be animated on click, for example var el = document.getElementById('element');

// Set will-change when the element is hovered el.addEventListener('mouseenter', hintBrowser); el.addEventListener('animationEnd', removeHint);

function hintBrowser() { // The optimizable properties that are going to change // in the animation's keyframes block this.style.willChange = 'transform, opacity'; }

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

固然對於用戶會反覆觸發的操做放在style中不移除也能夠

will-change屬性的值

  1. auto 表示沒有明確的意圖; 不管是啓發式和最優化,用戶代理應該應用都和正常狀況相同
  2. scroll-position 表示開發者指望去在接下來去改變或者有動畫應用元素的滾動位置
  3. contents 表示開發者指望去在接下來去改變或者有動畫應用元素的內容
  4. 用來排除關鍵字 will-change, none, all, auto, scroll-position, and contents, 從以外增長一些通用的關鍵字

    will-change: transform:
    will-change: opacity:
    will-change: top, left, bottom, right:

若是一個屬性無最初的值,在這個元素上這個屬性將建立一個堆棧的內容, 明確規定在will-change的屬性必須在這個元素上建立一個堆棧的內容.

若是一個屬性無最初的值, 這個屬性將形成這個元素產生一個包含區塊的固定定位的元素, 明確規定在 will-change的屬性必須形成這個元素產生一個包含區塊的固定定位的元素

瀏覽器兼容性

這個目前不樂觀,相信之後會好

imageimage

結束語

will-change能夠幫助咱們擺脫hack的硬件加速,可是能力越大、責任越大

Tab Atkins Jr

Set will-change to the properties you’ll actually change, on the elements that are actually changing. And remove it when they stop.

 

翻譯:http://selayou9527.github.io/2014/11/07/CSS%20will-change%20%E5%B1%9E%E6%80%A7/

原文: CSS will-change 屬性

相關文章
相關標籤/搜索