什么是重排和重绘,更改哪些属性会触发重排和重绘,如何避免?

2,789 阅读2分钟

什么是重排和重绘?

当DOM的样式或内容会被修改时,将触发重新渲染。除了属性值计算、单位换算外,渲染主要分为三个步骤:

  • 布局:计算盒模型的位置,大小

  • 绘制:填充盒模型的文字、颜色、图像、边框和阴影等可视效果

  • 合并:所有图层绘制后,按层叠顺序合并为一个图层 重新渲染一般有三种执行路径:

  • 重排:布局 → 绘制 → 合并

  • 重绘:绘制 → 合并

  • 合并 不同属性的修改,会触发不同的渲染路径

更改哪些属性会触发重排和重绘?

引起重排的属性,即布局类属性,包括:

类型属性名
盒模型display padding margin width height min-height max-height border border-width
定位和浮动position top bottom left right float clear
文字及溢出font-family font-size font-weight line-height text-align vertical-align white-space overflow overflow-y

引起重绘的属性,即绘制类属性,包括:

类型属性名
颜色color
边框border-color border-style border-radius
背景background background-image background-position background-repeat background-size
轮廓outline outline-color outline-style outline-width
可见性visibility
文字方向text-decoration
发光box-shadow

如何避免重排和重绘?

  • 尽量使用仅引起合成的属性
类型属性名
变形transform
透明度opacity
  • 限制重新渲染区域

    • 使用position:absoluteposition:fixed等方法创建层叠上下文
    • 使用contain:layoutcontain:paint等属性值,让当前元素和内容独立于 DOM 树
    • 减少使用display:table<table>表格布局
  • 利用浏览器自身优化

    引起回流、重绘的属性操作会放入队列,达到一定数量或时间,再一次渲染

    • 用变量缓存元素的属性值
    • 要设置的属性值减少依赖其它属性值
    • 避免频繁读取计算属性值
  • 手动一次渲染

    强制使用style.cssTextsetAttribute('style', 样式)将所有设置的属性,一次写入内联样式

  • 优化 DOM 树

    • 使用文档碎片或display:none隐藏节点,缓存要插入的节点,之后将缓存结果一次性插入 DOM 树并显示
    • 使用replaceChild``cloneNode减少先删除、创建再插入 DOM 的场景