DOM树和样式结构体 (浏览器所能识别的所有样式) 构建组成渲染树 (render tree) 来完成绘制页面
当渲染树的一部分发生改变, 若只引起页面的非布局外观 (如背景等) 发生改变时, 那这就是一次页面重绘(repaint);
若引起页面的布局发生改变, 那这就是一次页面回流 (reflow), 同时页面外观也发生改变, 意味着必然伴随重绘
从定义中可知何时会发生重绘与回流
回流
添加/删除元素
display: none;
定位, 浮动, 边距等改变位置
改变盒模型
改变文字大小, 粗细, 位置, 间隔, 行高, 超出容器处理方式等
改变浏览器大小
激活伪类 (:hover)
内容变化 (input等输入文字)
重绘
改变 visiblility: hidden; z-index, 轮廓, 颜色, 背景, 阴影, 倒影等
回流的代价远比重绘昂贵, 很大程度影响着页面性能, 减缓JavaScript
减少回流次数: 在页面加载时, 浏览器会把所有引起回流的操作在构建渲染树前排入一个队列, 并在出队列时批量处理,
然后执行一次页面绘制, 使这过程只发生一次回流当需要访问布局上的回流数据,
如窗口大小等, 样式中的盒模型, 偏移量等属性, 浏览器就会将这些回流操作提前处理一遍, 并执行一次页面绘制,
然后提供相关数据, 从而增加了一次页面回流
变量存储:
如果多次访问布局上的相同回流数据, 那么回流次数就增加了可以将要访问的相同数据存储为变量到内存, 然后再次访问相同数据时, 只要读取内存中的变量即可
避免用类名或样式属性来作为条件判断的依据
封装样式:
将需要改变的多个样式封装到一个类里, 然后只要改变className
若样式的属性值是动态的, 则用cssText, 如 element.syle.cssText +=';width: ' + 动态宽度变量 + 'px; height: ' + 动态高度变量 + 'px;';
img设置宽高, 避免页面加载后, 再为图片文件绘制宽高, 而产生回流
减小回流范围: 把引起回流的操作在构建渲染树或改变渲染树的一部分前进行批量处理, 然后执行一次页面绘制
添加多个节点时, 在还没添加到DOM前, 先把多个节点放到一个节点中, 然后只要把这样一个节点添加到DOM中, 使回流只发生在一个节点上
对元素进行多次操作前, 先用display: none; 让该元素离开DOM, 然后在操作结束后显示元素使回流只发生两次
在其他节点后面添加节点或改变样式, 只会自身产生回流; 在其他节点前添加节点或改变样式, 可能导致其他节点都产生回流
通过定位改变位置, 只会自身产生回流; 通过边距改变位置, 可能使其他节点也产生的回流
避免使用table和多层嵌套
避免在样式中用 expression(eval(...));
CPU优化: 浏览器会在主线程外为执行CSS3动画的节点创建一个图层, 并把节点移到图层上,
然后通过CPU或GPU将同一个动画的每个节点所创建的图层组合成一个图层添加到页面, 最后执行动画
这过程把节点移到图层上时产生了一个回流, 这个回流让同一个动画的每个节点都消失;
把图层添加到页面又产生了一个回流, 这个回流花费的时间基本决定了动画开始前的准备时间,
如果所花的时间较长, 就会看到这些节点消失的瞬间, 如果用CPU处理 (CPU处理图层不及GPU), 所花的时间会更长
综上可知, transform 和 opacity 的动画过程没有回流, 但动画前却是一场噩梦
开启设备硬件加速渲染, 即强制使用GPU进行2D绘图
用 translateZ() 或 translate3d() 代替 translate() 从而提高CPU的处理减少动画开始前的准备时间, 且不会随着抗锯齿而导出突变,
但依旧免不了回流所耗的时间, 而且过多 translateZ() 或 translate3d() 占用CPU使用率, 将导致CPU性能下降
-webkit-font-smoothing: antialiased/subpixel-antialiased; 抗锯齿缓解字体变虚
-webkit-backface-visibility: hidden; 解决rotate发生冲突而闪动
牺牲平滑度换取速度
每次1px移动一个动画, 可能导致动画及随后的回流占用了很高的CPU使用率, 动画就会看上去是跳动的,
因为浏览器正在与更新回流做斗争动画元素每次移动3px可能在非常快的机器上看起来平滑度低了,
但它不会导致在CPU较慢的机器和移动设备中抖动