回流与重绘
浏览器渲染过程
参考:https://zhuanlan.zhihu.com/p/561696825
解析 HTML 和计算样式(parsing and style calculation)把 HTML 解析成 DOM,把 CSS 解析成 CSSOM,DOM 和 CSSOM 合并渲染树(render tree)。
渲染树(render Tree)有 DOM 的结构和每个节点的样式,但这还不足以呈现页面,还需要计算节点在画面上的大小和位置,这个过程称为布局,并且这个过程中会产生一个布局树。
绘制拥有 DOM、样式和布局仍然不足以呈现画面,浏览器仍然必须判断元素的绘制顺序。
在前三个步骤中,浏览器已经获得了渲染页面所需的资讯,但为了提供整体渲染效率,浏览器会再透过合成,将资讯渲染到画面上。合成事一种将页面的哥哥部分分成图层(layers)的拘束,这个技术会在合成线程这个单独的线程执行。这个过程完成之后,还会再产生一个图层树,最终才渲染到画面上。
回流和重绘
当网页的结构、大小或位置发生变化时,浏览器需要重新计算的集合属性(如宽高、位置),这个过程称为回流。浏览器会重新构建渲染树并重新布局,可能还伴随重绘。
触发场景:
添加、删除 DOM 节点;
改变元素尺寸、位置(如
width,height,padding,margin,display,position等);读取引起回流的属性,如:
offsetTop,offsetHeight,scrollTop,getComputedStyle();操作样式时未使用合适的合并手段(如:一次设置多个 style);
当元素的视觉样式发生变化(如颜色、背景、边框等)但没有引起布局变化时,浏览器会重新绘制该元素,称为重绘。表现为仅更新像素,而不涉及布局计算。
触发场景:
修改
color,background-color,visibility,border-color等不会影响布局的样式更改元素的 className 但只影响了视觉;
性能影响
回流 > 重绘 > JS 运算:回流开销最大,因为它可能影响整个 DOM 树甚至触发多次重绘。
回流过程中会阻塞浏览器渲染和用户交互,影响页面流畅性。
优化建议
1. 避免频繁操作 DOM
将多次 DOM 操作合并为一次(如使用 DocumentFragment)
批量操作时先脱离文档流,如:
element.style.display = 'none'
2. 减少读取触发同步布局的属性
尽量避免立即访问
offsetXXX、scrollXXX等属性,或在批量读取前缓存需要的值
3. 使用 CSS3 合理替代
用
transform,opacity替代top/left,width/height,可避开回流,仅触发 GPU 加速的重绘或合成层变化
4. 避免逐帧修改样式
在动画中使用
requestAnimationFrame来协调更新时机合理使用
will-change提示浏览器预优化
最后更新于
这有帮助吗?