本文主要参考 🐻🐻🐻我只想使用will-change,又有什么错? - 掘金 (juejin.cn)
CSS 属性 will-change 为 web 开发者提供了一种告知浏览器该元素会有哪些变化的方法,这样浏览器可以在元素属性真正发生变化之前提前做好对应的优化准备工作。这种优化可以将一部分复杂的计算工作提前准备好,使页面的反应更为快速灵敏。
原理
当我们设置了will-change: transform 时,浏览器会为该元素创建一个独立的图层,将这个图层标记为“即将变换”。这样,在进行布局和绘制时,浏览器就可以更高效地处理这个元素,而无需重新计算整个渲染树,每一个元素单独加入 will-change 都会单独创建一个复合层,如果给大量的元素加上 will-change 就会创建大量的复合层,反而会影响性能
效果
- 减少渲染阻塞:浏览器可以提前分配和优化资源,减少渲染阻塞时间,提高页面的响应速度。
- 减少重绘和重排:浏览器可以更好地管理渲染过程,避免不必要的重绘和重排,从而提高渲染性能。
- 硬件加速:某些浏览器对
will-change属性会进行硬件加速,进一步提升性能。
时机
当元素有 will-change 时,将元素提升到它们自己的 GPU 层的浏览器。但有太多元素声明时,浏览器将忽略声明,以避免耗尽 GPU 内存
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";
}
iphone 问题
在 iphone 上如果给元素加上 will-change,可能出现模糊现象,分析一下问题
will-change 加入后,元素提升到复合层,浏览器其实会进行光栅化,光栅化的时候,设备比例的变化,导致绘制图像的过程变模糊
可以通过在执行完重排重绘后在适当的时机移除 will-change 解决
什么操作会将元素提升到复合层
在CSS中,以下属性可以将元素提升到复合层:
will-change属性:通过使用will-change属性,告诉浏览器该元素即将发生某种变化,浏览器可以提前将其提升到复合层以进行优化。transform属性:当使用 3D 或 2D 变换时,浏览器会自动将transform属性应用的元素提升到复合层。常见的变换函数如translate(),rotate(),scale()等。backface-visibility属性:当使用backface-visibility: hidden来隐藏元素的背面时,浏览器会将该元素提升到复合层。
结论
- 不要给大量的元素添加
will-change,这会导致创建大量的复合层 - 注意使用的时机,在需要进行重绘/重排行为的时候,才考虑加上
will-change,使用完后需要再适当的时机移除,释放浏览器资源 - 是否真的需要
will-change,如果页面在性能方面没什么问题,没有必要放个will-change