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属性的值

  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/

原文: CSS will-change 属性

时间: 2024-08-06 14:09:11

CSS will-change 属性的相关文章

CSS中连接属性的排序

在CSS超链接的属性中,有四个连接方式: a:link  a:hover a:visited a:acticve 之前在使用的时候一直是按照自认为的顺序中去写的,就是 L H V A的排序方式,然而有些时候却发现并不起作用了,查找了一些资料,也上网查找了一下,也有很多人在问及这个问题,如果是按照这种顺序排序,有时候显示正确,而有时候却显示不正确,追究原因,这个可能是由于浏览器的识别先后问题所导致的,也额能有缓存的原因在里面个人觉得,而最正确的写法应该是 L V H ,举个例子: <!DOCTYP

CSS中box-sizing属性的理解与部分用法

今天看了一些关于box-sizing的一些资料,在这里整理一下,希望也能对大家有所帮助. box-sizing是CSS的一个属性,很好的解决了盒模型的相关问题.CSS中的盒模型(Box model)分为两派,一派是W3C的标准模型,一派是IE的传统模型.那它们之间有什么不同的呢?首先需要明确它们都是对元素计算尺寸的模型,具体说就是对元素的width,height,padding,border以及元素实际尺寸的计算关系:而不同的地方就在于两者的计算方法不一至:(下面引用一些公式向大家展示一下两者的

CSS border边框属性教程(color style)

CSS 边框即CSS border-border边框样式颜色.边框样式.边框宽度的语法结构与应用案例教程篇 一.CSS 边框基础知识 CSS 边框即CSS border是控制对象的边框边线宽度.颜色.虚线.实线等样式CSS属性.同时大家可以进入码农教程提供CSS手册查看border手册:http://www.manongjc.com/cssref/pr_border.html 二.Html原始边框与DIV+CSS边框对照 Html表格控制边框:border="1" bordercolo

CSS中display属性:block、inline和inline-block的区别

最近写HTML遇到一个问题:我想设置span的宽度和高度,但是在IE9和chrome下总是不起效果.代码和效果图如下: <head> <style> span{ background-color:#43be60; width:100px; height:50px; margin-top:20px; margin-left:20px; } </style> </head> <body> <div style="background-

css常用样式属性详细介绍

对于初学css的来说,肯定会觉得这么多样式不好记,而且记住了也容易忘,其实刚开始我们不用去记这么多的样式,确实是记了也会忘,刚开始只需记住一些常用的就可以了,然后在慢慢的使用过程当中接触并学习一些高级点的,这才是一个靠谱的渐进过程,下面列出一些css常用属性,仅供参考 “文字”属性共有8项: 1.“字体”(font-family),设定时,需考虑浏览器中有无该字体. 2.“大小”(font-size),注意度量单位. 3.“粗细”(font-weight),除了normal(正常).bold(粗

CSS的display属性

网页设计中最常用的标签p.div.h1-h6(默认为块级元素),span(默认为内联元素) 1.把元素显示为内联元素和把元素显示为块级元素 <style type="text/css"> div{ display:inline; background:red;}/*区块元素将转换为内联元素*/ span{ display:block; background:green;}/*将内联元素转换为区块元素*/ </style> </head> <bo

css常用文本属性

[CSS常用文本属性] 1. 字体.字号类: ① font-weight: 字体粗细. bold-加粗.normal-正常.lighter-细体 也可以使用100-900数值,400表示normal,700表示bold ② font-style: 字体样式. italic-倾斜.normal-正常 ③ font-size: 字号. 可以写px单位,也可以写% 200%表示浏览器默认大小(16px)的两倍=32px ④ font-family: 字体系列(字体族). >>> 可以直接写字体

CSS中transform 属性

CSS中transform 属性允许你修改CSS可视化模型的坐标空间.通过transform,可以让元素进行移动(translate).旋转(rotate).缩放(scale).倾斜(skew). 如果该属性有一个非none值, 将会产生一个层叠上下文. 在这种情况下 对象将作为它包含的 position: fixed 元素的包含块(a containing block). 初始值 none 适用元素 transformable elements 是否是继承属性 否 Percentages re

CSS之cursor属性

今天学习了CSS的cursor属性,第一篇博客就用来总结它吧. cursor属性用于控制光标的显示样式,可取的值有这些: cursor:url()*|{auto|default|pointer|crosshair|text|vertical-text|help|not-allowed|no-drop|move|e-reszie|s-resize|w-resize|w-resize|n-resize|all-scroll|ne-resize|se-resize|nw-resize|sw-resiz

Css3之高级-3 Css多列属性(分隔列、列间隔、列规则、浏览器兼容性)

一.多列属性 分割列 - column-count 属性规定元素应该被分隔的列数 列间隔 - column-gap 属性规定列之间的间隔 列规则 - column-rule 属性规定列之间的宽度.样式和颜色 - 语法为: column-rule: width style color; 浏览器兼容性 - Internet Explorer 10 和 Opera 支持多列属性 - FireFox 需要前缀 -moz- - Chrome 和 Safari 需要前缀 -webkit- 总结:本章内容主要