介绍
若是你注意到在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/