CSS will-change 属性
介绍
如果你注意到在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加速,而是使用浏览器稍慢的软件渲染引擎。然而一些浏览器提供了hardware acceleration by means of certain properties来获取更高的渲染性能。 举个例子,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 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的属性必须造成这个元素产生一个包含区块的固定定位的元素
浏览器兼容性
这个目前不乐观,相信以后会好
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/
CSS will-change 属性的更多相关文章
- CSS之cursor属性
CSS之cursor属性 今天学习了CSS的cursor属性,第一篇博客就用来总结它吧. cursor属性用于控制光标的显示样式,可取的值有这些: cursor:url()*|{auto|defaul ...
- CSS样式常用属性整理
web工程师是最近5年刚刚兴起的一门高薪职业,人们的专注度越来越高. 那么前端除了学习html标签之外还需要掌握什么知识点呢? 为大家整理了一个和HTML标签密不可分的知识要点--<CSS样式常 ...
- CSS中box-sizing属性的理解与部分用法
今天看了一些关于box-sizing的一些资料,在这里整理一下,希望也能对大家有所帮助. box-sizing是CSS的一个属性,很好的解决了盒模型的相关问题.CSS中的盒模型(Box model)分 ...
- 深入理解css中position属性及z-index属性
深入理解css中position属性及z-index属性 在网页设计中,position属性的使用是非常重要的.有时如果不能认识清楚这个属性,将会给我们带来很多意想不到的困难. position属性共 ...
- CSS Counters 计数属性
CSS Counters其实就是一计数器,早期在CSS中计数器仅存在于ul和ol元素.如果要使用在div这样的元素上,只能通过list-style-image或者是元素的backgroud-image ...
- 利用CSS的@font-face属性 在网页中嵌入字体
字体使用是网页设计中不可或缺的一部分.网页是文字的载体,我们希望在网页中使用某一特定字体,但是该字体并非主流操作系统的内置字体,这样用户在浏览页面的时候就有可能看不到真实的设计. 美工设计师最常做的办 ...
- CSS中Position属性
也许你看到这个标题觉得很简单,确实这是一篇关于CSS中Position属性基础知识的文章,但是关于Position的一些细节也许你不了解. 1.简介 position有五个属性: static | r ...
- [转] CSS float 浮动属性
http://www.cnblogs.com/polk6/p/3142187.html CSS float 浮动属性 本篇主要介绍float属性:定义元素朝哪个方向浮动. 目录: 1. 页面布局方式: ...
- CSS背景特殊属性值
CSS代码示例-背景附着属性(background-attachment)-[背景图固定不动,不跟随滚动条滚动]:<html><head><title>背景附着属性 ...
- 怎样通过css的media属性,适配不同分辨率的终端设备?
怎样通过css的media属性,适配不同分辨率的终端设备,示比例如以下: <!DOCTYPE html> <html> <head> <title>首页 ...
随机推荐
- 全文搜索 Lucene.Net
Lucene简介 首先说明的是--Lucene.Net只是一个全文检索开发包,不是一个成型的搜索引擎, 它的功能就是负责将文本数据按照某种分词算法进行切词,分词后的结果存储在索引库中,从索引库检索数据 ...
- zend studio汉化
在help菜单中选择Install New Software,在 work with栏中添加上这样的地址 http://archive.eclipse.org/technology/babel/upd ...
- cpu对各种运算的速度对比
今天忽然想到cpu对各种基本运算的速度对比,我对比了异或,加法和乘法,结果发现速度时间,加法小于乘法小于异或, 原本我以为异或会是最快的,结果异或是最慢的,这跟cpu中的alu算术逻辑单元的实现有关, ...
- 10款最好的 Bootstrap 3.0 免费主题和模板
Twitter Bootstrap 框架已经广为人知,用于加快网站,应用程序或主题的界面开发,并被公认为是迄今对于Web开发的最有实质性帮助的工具之一.在此之前的,各种各样的界面库伴随着高昂的维护成本 ...
- CentOS6.3 编译安装LAMP(3):编译安装 MySQL5.5.25
所需源码包: /usr/local/src/MySQL-5.5.25/cmake-2.8.8.tar.gz /usr/local/src/MySQL-5.5.25/mysql-5.5.25.tar.g ...
- rails enum用于存储数据
http://api.rubyonrails.org/classes/ActiveRecord/Enum.html 新的项目中有一个字段是展示类型,可以用下拉框去做,用string存储具体的类型字段. ...
- Is there a difference between `==` and `is` in Python?
There is a simple rule of thumb to tell you when to use == or is. == is for value equality. Use it w ...
- 我常用的Vi命令
Vi对于linux的重要性和受欢迎的程度在此一律不表.此刻互联网上不少介绍vi的文章和博客,相信写得比我好的也不在少数.然而为什么我依然写这样一篇文章呢?我对linux知识和了解也都来自于互联网,很难 ...
- HTML5本地缓存数据
//HTML5本地缓存数据 function putObj(key, data) { if (!!window.localStorage) { var obj = { "key": ...
- Linux网络管理2---(网络环境查看命令、网络测试命令)
1.网络环境查看命令 ifconfig命令 查看或临时修改网络状态的命令 可以看到IP.子网掩码……信息 关闭和启动网卡 ifdown 网卡设备名(比如: ifdown eth0):禁用该网卡设备 i ...