# 回流(重排)

当render tree中的一部分(或全部)因为元素的 规模尺寸布局隐藏等改变而需要重新构建。 这就称为回流(reflow)。

当页面布局和几何属性改变时就需要回流

# 重绘

当render tree中的一些元素需要更新属性, 而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。

回流必将引起重绘,而重绘不一定会引起回流

# 触发页面重新布局的属性

  1. 盒子模型相关属性会触发重布局
  2. 定位属性及浮动也会触发重布局
  3. 改变节点内部文字结构也会触发重布局

盒子模型相关属性

  • width
  • height
  • padding
  • margin
  • display
  • border-width
  • border
  • min-height

定位属性及浮动

  • top
  • bottom
  • left
  • right
  • position
  • float
  • clear

文字结构

  • text-align
  • overflow-y
  • font-weight
  • overflow
  • font-family
  • line-height
  • vertival-align
  • white-space
  • font-size

# 只触发重绘的属性

  • color
  • border-style
  • border-radius
  • visibility
  • text-decoration
  • background
  • background-image
  • background-position
  • background-repeat
  • background-size
  • outline-color
  • outline
  • outline-style
  • outline-width
  • box-shadow

# 如何优化

  1. 避免使用触发重绘,回流的css属性。
  • 用translate替代top。 translate不会触发回流。
  • 用opacity替代visibility。 opacity不会触发回流和重绘。
  1. 将重绘,回流的影响范围限制在单独的图层之内。 给需要频繁更新的元素设置 transtrom, will-change属性,这时会新建一个图层。 他们的回流重绘不会影响其他图层。

  2. 不要一条一条地修改 DOM 的样式,预先定义好 class,然后修改 DOM 的 className

div.width = '100px';
div.height = '100px';
div.top = '100px';
.action {
  width:'100px';
  height:'100px';
  top: '100px';
}

div.className = 'action';
  1. 把 DOM 离线后修改,比如:先把 DOM 给 display:none (有一次 Reflow), 然后你修改100次,然后再把它显示出来. 因为修改display:none 的元素不会触发回流重绘。

  2. 不要在循环里读取位置属性,例如offsetHeight,offsetWidth, clientHeight, clientWidth.

let doms = [];
for(var i = 0; i < doms.length; i++) {
  let clientHeight = doms[i].clientHeight;
}
  1. 不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局
  2. 动画实现的速度的选择
  3. 对于动画新建图层
  4. 使用 transform:translateZ(0) transform:translate3d(0,0,0) 启用 GPU 硬件加速.