某人

此前素未谋面、此后遥遥无期

0%

重绘[repaints]/回流[reflows]

目的

为了提高页面性能,因为重排的消耗较大而且直接影响用户界面,它们将会给响应式网站以及 web APP 造成较大的影响。

定义

重绘[repaints]

重绘是指元素外观的改变所触发的浏览器行为,例如,color/visibility/outline/background-color。等属性引起的元素外观的改变。

回流[reflows]

回流又叫重排,是指浏览器计算页面的全部或部分布局所做的处理。调整浏览器窗口大小,使用伪类(比如 :hover),以及使用JavaScript 操作DOM,影响到页面布局事件的发生,就会导致重排。

同步重排[synchronous reflows]

Web 控制台可以通过记录重排事件来显示出这个重排消耗的时间,如果是由 JavaScript 触发的重排,这个时间是指同步重排(synchronous reflows)时消耗的时间。

重排的原因

  • 调整窗口大小
  • 字体的大小
  • 触发元素的伪类(:hover)
  • dom元素的增加、删除,大小改变
  • 其他的改动scrollTop、scrollLeft、offsetWidth等的值

解决方案

  1. 避免使用css的JavaScript表达式(仅IE浏览器)
  2. 应用元素的动画,使用 position 属性的 fixed 值或 absolute 值。
    因为它们已经脱离了正常文档流,动画效果应用到它们的元素上,不影响其他元素的布局,所它他们只会导致重新绘制,而不是一个完整回流。消耗会低一些。
  3. 避免使用table布局,
    表格中某一个单元格内容过宽,而引起其他列大小的改变,就会使布局发生改变,而引起其他节点的重排
  4. 牺牲平滑度
    Opera建议牺牲平滑度换取速度,每次1像素移动一个动画,但此动画及随后的回流使用了100%的CPU,动画就会看上去是跳动的,因为浏览器正在与更新回流做斗争,动画元素每次移动3像素可能在非常快的机器上看起来平滑度低了,但它不会导致CPU在较慢的机器和移动设备中抖动。
  5. 改变元素的class名,修改元素样式,如下
    1
    2
    3
    4
    5
    6
    7
    8
    <style type="text/css">
    .normal{width:300px;height:200px;font-size:14px;}
    .change{background:red;border:5px solid grey;height:300px;font-size:20px;}
    </style>
    <div id="box" class="normal">盒子</div>
    <script type="text/javascript">
    document.getElementById('box').className = 'normal change';
    </script>
  6. 避免设置多项内联样式,DOM交互是很慢,交替的修改和读取一个正在被操作元素的样式,每当你在读取前一次修改的样式时都会强制执行了同步重排.尽量不要出现类似如下的写法(推荐5):
    1
    2
    3
    4
    5
    6
    7
    8
    <div id="box" class="normal">盒子</div>
    <script type="text/javascript">
    var box = document.getElementById('box');
    box.style.background = 'red';
    box.style.border = '5px solid grey';
    box.style.height = '300px';
    box.style.fontSize = '20px';
    </script>
  7. 尽可能在DOM树的里面改变class,可限制回流的范围,使其影响尽可能少的节点。

PS

重绘可能引发回流,回流必定引发重绘

FireFox(火狐浏览器)

参考链接

回流与重绘-张鑫旭