CSS的will-change,為什么有時候能優(yōu)化幾十倍的性能?
作者:超神熊貓
https://juejin.cn/post/7254397517968867365
前言
will-change 一個既陌生又熟悉的屬性,以前在使用這個屬性的時候,單純是因為要做性能優(yōu)化,加上will-change會使得動畫變得流暢一些,但是實際上到底是什么原因導致加上will-change就能使得動畫流暢,它有什么弊端?
一個老同事,前幾天跟我說他挨了領導的罵,說他濫用will-change這個屬性,知其然不知其所以然。
我有點茫然,使用will-change應該是好事,能夠提升性能
但是當他給我介紹他的用法的時候,我想說的是,“罵你的隊伍能加我一個不咯?”
html
復制代碼
<template>
<div class="list">
<div class="item" v-for="i,k in lists" :key="k">
...
</div>
</div>
</template>
<style>
.item {
will-change: transform;
}
</style>
給一個循環(huán)的元素加入了will-cahnge,這意味著網(wǎng)頁上會有大量的元素加入了will-change,并且長留存
在現(xiàn)代網(wǎng)頁設計中,性能優(yōu)化成為了一個重要的議題。一種關鍵的優(yōu)化工具是CSS屬性
will-change,它可以告訴瀏覽器元素將要發(fā)生的變化,從而提前分配資源并優(yōu)化渲染。本文將深入探討will-change的使用和原理,以幫助開發(fā)者充分發(fā)揮其潛力,提升網(wǎng)頁性能。
一、什么是will-change?
will-change是一個CSS屬性,它可以告訴瀏覽器某個元素將要發(fā)生的變化。通過明確指定這些變化,瀏覽器可以事先分配和優(yōu)化相應的資源,從而提升渲染的性能。
二、will-change的使用方法
要使用will-change,只需將它應用于你要進行性能優(yōu)化的元素上。
css
復制代碼
.element {
will-change: transform;
}
在上述示例中,我們告訴瀏覽器,該元素即將發(fā)生變換(transform),以便瀏覽器在渲染時提前分配所需的資源。
值得注意的是,因為will-change是為了性能優(yōu)化而設計的,濫用它可能會帶來負面影響。只在需要優(yōu)化的元素上使用will-change,避免對所有元素都進行指定。
三、will-change的原理
要理解will-change的原理,我們需要了解瀏覽器渲染流程的基本概念。
1. 渲染流程簡介
瀏覽器在渲染網(wǎng)頁時,會經(jīng)歷一系列的步驟,如樣式計算、布局、繪制和合成。為了提高性能,瀏覽器會盡量避免進行不必要的計算和操作。
2. will-change的作用
will-change的作用就是告訴瀏覽器某個元素將要發(fā)生的變化,從而使瀏覽器在渲染過程中提前分配和優(yōu)化相應的資源。
例如,當我們設置了will-change: transform時,瀏覽器會為該元素創(chuàng)建一個獨立的圖層,將這個圖層標記為“即將變換”。這樣,在進行布局和繪制時,瀏覽器就可以更高效地處理這個元素,而無需重新計算整個渲染樹。
加入will-change后,通過觀察復合層,如圖下
layer-start.gif
加入will-change后,元素會被提升到單獨的復合層,動畫(重繪、重排)的操作只會在單獨復合層上進行,減少了原來的頁面層重繪和重排的行為 注:每一個元素單獨加入will-change都會單獨創(chuàng)建一個復合層,如果給大量的元素加上will-change就會創(chuàng)建大量的復合層,反而會影響性能
3. will-change的優(yōu)化效果
使用will-change可以帶來以下優(yōu)化效果:
- 減少渲染阻塞:瀏覽器可以提前分配和優(yōu)化資源,減少渲染阻塞時間,提高頁面的響應速度。
- 減少重繪和重排:瀏覽器可以更好地管理渲染過程,避免不必要的重繪和重排,從而提高渲染性能。
- 硬件加速:某些瀏覽器對
will-change屬性會進行硬件加速,進一步提升性能。
4. will-change使用的時機
在很多關于will-change的描述,都能夠看到類似下面的一段話
在實際更改的元素上將 will-change 設置為您將實際更改的屬性。并在他們停止時將其刪除。- Tab Atkins Jr.(規(guī)范編輯者)
至于為什么?大部分的描述都是因為will-change會消耗瀏覽器GPU資源
當元素有 will-change 時,將元素提升到它們自己的“GPU 層”的瀏覽器。但有太多元素聲明時,瀏覽器將忽略聲明,以避免耗盡 GPU 內存
所以對于will-change的使用應該控制時機
ray-so-export (1) (1).png
在適當?shù)臅r機移除will-change就是減少瀏覽器的復合層,避免過度使用will-change帶來性能問題
四、iphone上使用will-change會導致圖片模糊、文字模糊問題
在iphone上可以看到如果給元素加上will-change,可能出現(xiàn)模糊現(xiàn)象,分析一下問題
- 加入will-change,元素會提升到復合層,提升到復合層后,瀏覽器做了什么事?
- 安卓不會而iphone會,iphone上使用的是safari瀏覽器
解:
- will-change加入后,元素提升到復合層,瀏覽器其實會進行 光柵化
- 至于為什么safari瀏覽器在元素提升到復合層后,進行光柵化會導致模糊問題,在我們翻閱了各家瀏覽器內核論壇后,找到一些資料 groups.google.com/a/chromium

大概的內容就是:
在2016年之前,不止safari,谷歌瀏覽器也是存在模糊的問題,原因是提升復合層后,光柵化的時候,設備比例的變化,導致繪制 圖像 的過程變模糊,谷歌是在2016年解決的這個問題,所以現(xiàn)在看來我們會在iphone上發(fā)現(xiàn)模糊問題,在安卓機上并不會
iphone上模糊的問題,可以通過在執(zhí)行完重排重繪后在適當?shù)臅r機移除will-change(讓元素回到原來的頁面層,不在單獨一個復合層)就可以解決
五、什么操作會將元素提升到復合層
在CSS中,以下屬性可以將元素提升到復合層:
-
will-change屬性:通過使用will-change屬性,告訴瀏覽器該元素即將發(fā)生某種變化,瀏覽器可以提前將其提升到復合層以進行優(yōu)化。 -
transform屬性:當使用 3D 或 2D 變換時,瀏覽器會自動將transform屬性應用的元素提升到復合層。常見的變換函數(shù)如translate(),rotate(),scale()等。 -
backface-visibility屬性:當使用backface-visibility: hidden來隱藏元素的背面時,瀏覽器會將該元素提升到復合層。
需要注意的是,將元素提升到復合層也會增加內存的占用和渲染的復雜性,因此不應濫用。只有當元素需要頻繁改變或有復雜的動畫效果時,才建議將其提升到復合層。
六、結論
will-change是一種強大的性能優(yōu)化工具,在現(xiàn)代網(wǎng)頁設計中發(fā)揮著重要作用。通過明確指定元素將要發(fā)生的變化,瀏覽器可以提前分配和優(yōu)化相應的 .
使用上也有需要注意的點:
1. 不要給大量的元素添加will-change,這會導致創(chuàng)建大量的復合層
2. 注意使用的時機,在需要進行重繪/重排行為的時候,才考慮加上will-change,使用完后需要再適當?shù)臅r機移除,釋放瀏覽器資源
3. 是否真的需要will-change,如果頁面在性能方面沒什么問題,沒有必要放個will-change來換取那微乎其微的收益,如果收益客觀,可加,如果加與不加,差別不大,沒必要
推薦閱讀 點擊標題可跳轉