介紹
若是你注意到在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屬性的值
- auto 表示沒有明確的意圖; 不管是啓發式和最優化,用戶代理應該應用都和正常狀況相同
- scroll-position 表示開發者指望去在接下來去改變或者有動畫應用元素的滾動位置
- contents 表示開發者指望去在接下來去改變或者有動畫應用元素的內容
-
用來排除關鍵字 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的屬性必須形成這個元素產生一個包含區塊的固定定位的元素
瀏覽器兼容性
這個目前不樂觀,相信之後會好
結束語
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/