CSS will-change 属性
发布日期:2021-09-04 22:25:58 浏览次数:33 分类:技术文章

本文共 4232 字,大约阅读时间需要 14 分钟。

介绍

如果你注意到在webkit的浏览器上“flicker”一些CSS操作(尤其是变形和动画方面的)的表现,你很可能之前就注意过硬件加速

CPU、GPU和硬件加速

硬件加速意味着Graphics Processing Unit(GPU)会通过代替Central Processing Unit (CPU)做一些负荷比较大的事情,来协助浏览器快速渲染页面,当CSS操作使用硬件加速的时候,通常会使页面渲染速度加快

顾名思义,CPU和GPU都是计算机处理单元。CPU在电脑主板,几乎处理电脑的一切操作,有电脑大脑之称;GPU在显卡上,负责处理和渲染图形。此外GPU通过特殊的设计,使其擅长于渲染图形所需的数学和几何运算。因此把操作转嫁到GPU可以获得显著的性能提升,同时也可以减少移动设备CPU的争用。

硬件加速(或者说GPU加速)依赖于浏览器渲染页面使用的layering model,当特定的操作(CSS 3D变形)作用于页面上的一个元素,元素移动到它自己的layer,在这个layer中元素合一不受页面其他元素的干扰独立渲染,然后复合到页面中去。在这种隔离内容渲染的工作方式下,如果页面的变化仅仅是该元素的变形,其余部分不必被重新渲染,这会带来显著的速度优势。值得注意的是只有3D变形会有自己的layer,2D变形不会。

CSS的动画、变形、渐变并不会自动的触发GPU加速,而是使用浏览器稍慢的软件渲染引擎。然而一些浏览器提供了来获取更高的渲染性能。 举个例子,opacity属性是几个能够加速的属性之一,因为GPU可以方便的处理。基本上任何层的透明度渐变浏览器都会交给GPU处理来加速。除了opacity能够使用GPU处理的就是CSS 3D变形了

translateZ() (or translate3d()) Hack

很长一段时间内我们都通过translateZ()或者translate3d() hack来骗取浏览器触发硬件加速,具体做法就是为元素添加没有变化的3D变形,比如元素在2维空间可以通过添加以下CSS来硬件加速

transform: translate3d(0, 0, 0);

所谓硬件加速就是创建了一个被传递到GPU处理的层的操作,然而强制使用hack方式创建layer并不是长久之计,创建layer的技术可以使页面加速,但是也有代价:它们占用RAM和GPU存储空间(考虑到移动设备的存储容量有限),所以必须呗小心使用,确保这么做真的对页面渲染有所帮助

为了避免创建layer的hacks,一个允许我们提前通知浏览器我们将对元素做何种变化的CSS属性被引入,这样浏览器可以优化处理元素渲染的方式,为元素提前准备昂贵的动画处理操作,这就是wiil-change属性

牛逼的 will-change属性

will-change属性可以提前通知浏览器我们要对元素做什么动画,这样浏览器可以提前准备合适的优化设置。这样可以避免对页面响应速度有重要影响的昂贵成本。元素可以更快的被改变,渲染的也更快,这样页面可以快速更新,表现的更加流畅。

举个例子,当对于素使用 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 examplevar 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的属性必须造成这个元素产生一个包含区块的固定定位的元素

浏览器兼容性

这个目前,相信以后会好

image

结束语

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/

原文: 

转载地址:https://blog.csdn.net/weixin_34226182/article/details/85683053 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Android URI简单介绍
下一篇:微软职位内部推荐-Principal Group Program Manager

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年03月20日 23时40分27秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

java list二分查找_java中的ArrayList和LinkedList的二分查找速度比 | 学步园 2019-04-21
php中的变量名称用什么表示,PHP变量,方法,类等名称中的有效字符是什么? 2019-04-21
pic32mx是什么cpu_PIC32MX单片机外设库使用(Ⅰ)- 系统时钟及I/O口基本设置 2019-04-21
用c 在mysql上存图片_C 批量保存图片进 mysql 利用MYSQL_BIND插入longblob 2019-04-21
mysql 1045 28000_mysql报关于用户密码1045(28000),几种处理方法 (zhuan) 2019-04-21
solr比mysql的优势_Solr与Elasticsearch的优缺点比较总结和归纳 2019-04-21
华为博士招聘上机考试题目_牛客网-华为-2020届校园招聘上机考试-3 2019-04-21
python中for可以做变量名吗_Python中使用动态变量名的方法 2019-04-21
mysql 日期转换天数_MySQL 日期操作 增减天数、时间转换、时间戳 2019-04-21
java对象去重复_JAVA中List对象去除重复值的方法 2019-04-21
java bss_[转] .bss段和.data段的区别 2019-04-21
java上传图片损坏_大神求助 上传图片后 图片损坏 2019-04-21
java socket唯一标识符_Java Socket编程之常识网络基础知识 2019-04-21
java给xyz大小排序_java递归实现string xyz排序 2019-04-21
arctime必须要java_Arctime使用教程 Arctime常见问题解答 2019-04-21
mysql pxc mysql5.7_mysql之PXC5.7.18集群系列——1. Percona XtraDB Cluster 搭建 2019-04-21
mysql 自适应字段宽度_box-sizing解决自适应布局容器宽度问题 2019-04-21
java 配置文件配置路径_Java读取配置文件路径设置 2021-06-24
vux 选择器_vue中的scoped分析以及在element-UI和vux中的应用 2021-06-24
java cache 有效期_springboot cache 自定义过期时间及自定义缓存key前缀 2021-06-24