本文原创:fanjiayucss
chrome团队提出了一个以用户为中心的性能模型被称为RAIL,它为工程师提供一个目标,只要达到目标的网页,用户就会以为很流畅;它将用户体验拆解为一些关键操做,例如:点击,加载等;并给这些操做规定一个目标,例如:点击一个按钮后,多长时间给反馈用户会以为流畅。html
RAIL将影响性能的行为划分为四个方面,分别是:response(响应)、animation(动画)、idle(空闲)与load(加载)。没错,RAIL这个名字来自于这四个单词的首字母,方便记忆。css3
JavaScript:通常来讲,咱们会使用JavaScript来实现一些视觉变化的效果。chrome
Style:计算样式。这个过程是根据CSS选择器,对每一个DOM元素匹配对应的CSS样式。浏览器
Layout:布局。具体计算每一个DOM元素最终在屏幕上显示的大小和位置。Web页面中元素的布局是相对的,所以一个元素的布局发生变化,会联动地引起其余元素的布局发生变化。所以,对于浏览器而言,布局过程是常常发生的。bash
Paint:绘制。本质上就是**填充像素的过程。**包括绘制文字、颜色、图像、边框和阴影等,也就是一个DOM元素全部的可视效果。通常来讲,这个绘制过程是在多个层上完成的。布局
Composite:渲染层合并。性能
若是你修改一个DOM元素的“layout”属性,也就是改变了元素的样式(好比width、height或者position等),那么浏览器会检查哪些元素须要从新布局,而后对页面激发一个reflow(重排)过程完成从新布局。reflow一定会引起重绘,这对于WEB的性能影响是极大的。测试
影响WEB性能主要过程包括layout、paint和composite。那么对于cssanimation而言,咱们的全部操做都是经过CSS的样式控制动画,只要是会触发layout、paint和composite的CSS属性都会直接影响动画的性能。因此整个动画应尽可能避开重排和重绘。字体
会触发重排重绘:调整窗口大小、改变字体、增长或者移除样式表、内容变化、激活CSS伪类、计算offsetwidth和offsetheight等等。
影响layout的CSS属性:csstriggers.com/
####防止FSL(强制同步布局)
以下代码为会触发FSL的一段代码
<body>
<button id="btn">Click me~</button>
<div class="container">
<!-- 建立多个class为box的div使效果更明显>
<div class="box"></div>
</div>
<script>
const btn = document.querySelector('#btn');
const container = document.querySelector('.container');
const boxes = document.querySelectorAll('.box');
btn.onclick = function () {
for (var i = 0; i < boxes.length; i++) {
boxes[i].style.width = container.offsetWidth + 'px';
}
}
</script>
</body>
复制代码
对代码进行以下优化
<script>
const btn = document.querySelector('#btn');
const container = document.querySelector('.container');
const boxes = document.querySelectorAll('.box');
btn.onclick = function () {
const newWidth = container.offsetWidth;
for (var i = 0; i < boxes.length; i++) {
boxes[i].style.width = newWidth + 'px';
}
}
</script>
复制代码
从对比中能够看出,前者的Rendering是后者的几倍之多,可见,优化重排重绘,防止FSL的发生对性能的提高效果是很明显的。
####新建图层
事实上浏览器在渲染页面时,能够将页面分为不少个图层,有点相似于photoshop,一张图片在potoshop中是由多个图层组合而成,而浏览器最终显示的页面实际也是由多个图层构成的。
因此将本来不断发生变化的元素提高到单独的图层中,就再也不须要绘制了,浏览器只须要将两个图层合并在一块儿便可。(注:图层的维护也须要成本,不要一味地不断新建图层)
<body>
<div class="ball-running" style="width:100px;height:50px;background:red;position:absolute;left:0;top:0"></div>
</body>
<style>
.ball-running { animation: run-around 4s infinite;}
@keyframes run-around {
0%: { top: 0; left: 0; }
25% { top: 0; left: 200px; }
50% { top: 200px; left: 200px; }
75% { top: 200px; left: 0; }
}
</style>
复制代码
<body>
<div class="ball-running" style="width:100px;height:50px;background:red;position:absolute;left:0;top:0"></div>
</body>
<style>
.ball-running { animation: run-around 4s infinite; }
@keyframes run-around {
0%: { transform: translate(0, 0); }
25% { transform: translate(200px, 0); }
50% { transform: translate(200px, 200px); }
75% { transform: translate(0, 200px); }
}
</style>
复制代码
JS动画要保证预留出6ms的时间给浏览器处理像素管道,而自身执行时间应该小于10ms来保证总体运行速度小于16ms。
避免一切FSL,它很是影响性能。
CSS动画尽可能使用transform属性来完成动画。建议使用transform的translate替代margin或position中的top、right、bottom和left,同时使用transform中的scalex或者scaley来替代width和height。