重绘和回流

305 阅读2分钟

浏览器的渲染过程

  1. 解析 HTML 构建 DOM 树,并行请求 css/image/js
  2. CSS 文件下载完成后被 CSS 解析器解析成 CSSOM 树
  3. 结合 DOM 和 CSSOM 树,生成一棵渲染树(Render Tree)
  4. 布局(Layout),计算出每个节点在屏幕中的位置
  5. 将布局显示(Painting)在屏幕上

重绘

当元素的属性改变且不影响元素的布局时会发生重绘。

会导致一些重绘的操作

  • color
  • border-style
  • visibility
  • backgroud
  • text-decoration
  • backgroud-image
  • backgroud-postion
  • background-repeat
  • background-size
  • outline
  • outline-color
  • outline-style
  • box-shadow

回流

当元素的集合属性发生改变,并且影响元素的布局时会发生回流。回流的性能消耗是非常的大的,应尽量避免回流的操作。

会导致回流的操作

  • 页面首次渲染
  • 浏览器窗口大小发生改变
  • 元素尺寸或位置发生改变
  • 元素内容变化(文字数量或图片大小等等)
  • 元素字体大小变化
  • 添加或者删除可见的DOM元素
  • 激活CSS伪类(例如::hover)
  • 查询某些属性或调用某些方法

会导致回流的一些属性的查询

clientWidth clientHeight clientLeft clientTop

offsetWidth offsetHeight offsetLeft offsetTop

scrollWidth scrollHeight scrollTop scrollLeft

getBoundingClientRect() scrollIntoView

如何减少重绘和重拍

1. 对动画元素使用absolute / fixed 属性

2. 离线操作

  • 隐藏要操作的 DOM。在要操作 dom 之前,通过 display 隐藏 dom,然后尽量的进行多次修改操作,当操作完成之后,才将元素的 display 属性为可见,因为不可见的元素不会触发重排和重绘。
  • 通过使用 DocumentFragment 创建一个文档碎片,在它上面批量操作 dom,操作完成之后,再添加到文档中,这样只会触发一次重排。
  • 复制节点,在副本上工作,然后再替换原来的元素

3. 样式修改合并成一次操作,比如可以通过增加class类名

4. 使用resize事件做好防抖节流