前端性能优化之重绘和重排(Repaints and Reflow)

浏览器下载完页面中的所有组件——HTML 标记、JavaScriptCSSimages————之后会解析并生成两个内部数据结构

DOM Tree

表示页面结构

Render Tree

表示DOM节点如何显示

浏览器的渲染过程

1、处理HTML标记并构造DOM
2、处理CSS标记并构造CSSOM
3、将DOMCSSOM合并成一个渲染树
4、根据渲染树(Render Tree)来布局,以计算每个节点的几何信息
5、将各个节点绘制到屏幕

生成Render Tree渲染树

render-tree

触发重排(Reflow)和重绘(Repaint)

DOM元素的添加、修改(内容)、删除(Reflow + Repaint)
仅修改DOM元素的字体颜色(只有Repaint,因为不需要调整布局)

重绘(Repaints)

当页面中DOM元素样式以及可见性visibility发生改变的时候,但是并不影响布局(eg: coloroutlinevisibilitybackground-color等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘(Repaints)

重排(Reflows)

Render Tree 中涉及到部分或整个页面的布局, 因元素的尺寸(Size)布局(Layout)隐藏(Display)等改变而需要重新构建导致了其所有子元素以及DOM中紧随其后的祖先元素的随后的浏览器重新渲染的过程称为 重排(Reflows)

哪些操作会导致浏览器的重排(Reflows)呢?

  • 添加或删除可见的 DOM 元素
  • 元素位置改变
  • 元素尺寸改变(包括:margin(外边距)、padding(内边距)、border-width(边框厚度)、width(宽度)、height(高度)等属性改变)。
  • 页面渲染器初始化
  • 调整浏览器窗口大小(Resizing the window)
  • 改变字体(Changing the font)
  • 增加或移除样式表(Adding or removing a stylesheet)
  • 内容变化,比如用户在input框中输入文字(Content changes, such as a user typing text in an input box),文本改变成图片被另一个不同尺寸的图片替代
  • 激活CSS伪类,比如::hover(IE 中为兄弟结点伪类的激活)(Activation of CSS pseudo classes such as :hover (in IE the activation of the pseudo class of a sibling))
  • 操作class属性(Manipulating the class attribute)
  • 脚本操作DOM(A script manipulating the DOM)
  • 计算 offsetWidthoffsetHeight 属性(Calculating offsetWidth and offsetHeight)
  • 设置 Style 属性的值 (Setting a property of the style attribute)

总结:

重排必将引起重绘,重绘不一定会引起重排。

性能影响

有时即使仅仅重排(Reflow)一个单一的元素,它的父元素以及任何跟随它的元素也会产生重排(Reflow)

现代浏览器会对频繁的重排(Reflow)或重绘(Repaints)进行优化:

由于每次重排都会产生计算消耗,大多数浏览器可通过队列化修改并批量执行来优化重排过程。

可通过以下方法强制刷新队列并要求计划任务立刻执行。获取布局信息的操作会导致队列刷新,比如以下方法:

  • offsetTopoffsetLeftoffsetWidthoffsetHeight
  • scrollTopscrollLeftscrollWidthscrollHeight
  • clientTopclientLeftclientWidthclientHeight
  • scrollIntoView()scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。

优化重绘重排

如何避免重排(Reflow)或将它们对性能的影响降到最低?

参考文章