HTML的渲染流程
- 解析HTML,生成DOM树(Document Object Model Tree)
- 解析css,构建CSSOM(CSS Object Model Tree)
- 合并DOM和CSSOM构建渲染树(Render Tree)
- 布局,计算每个元素在屏幕上的位置和大小(这个阶段也叫回流/重排)
- 绘制:将渲染树中的每个节点转换为屏幕上的实际像素(重绘)
- 合成:将多个层合并为最终的视觉输出。
重排(回流)
-
定义: 当渲染树中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建时,就会发生重排。这意味着浏览器需要重新计算元素的几何属性(位置和大小),并重新构建渲染树,然后将渲染树绘制到屏幕上。重排是一个代价高昂的操作,因为它会影响到页面的布局,可能导致一系列元素的位置和尺寸发生变化。
-
触发重排的操作:
- 改变窗口大小:当浏览器窗口的大小发生改变时,页面中元素的布局可能需要重新计算,以适应新的窗口尺寸,这会触发重排。例如,用户拖动浏览器窗口的边框来调整窗口的宽度或高度。
- 改变字体大小:字体大小的改变会影响文本占据的空间大小,进而可能影响到周围元素的布局,从而触发重排。比如,通过 CSS
font - size属性改变字体大小。 - 添加或删除可见的 DOM 元素:添加新的 DOM 元素或者删除已有的 DOM 元素,会改变渲染树的结构,导致浏览器重新计算布局,触发重排。例如,使用 JavaScript 的
document.createElement()创建新元素并添加到 DOM 树中,或者使用removeChild()方法删除元素。 - 改变元素的位置:改变元素的
top、left、right、bottom等定位属性,或者修改display属性(例如从none改为block或反之),会使元素的位置或布局发生变化,从而触发重排。 - 改变元素的尺寸:修改元素的
width、height、padding、margin等属性,会改变元素的大小和占据的空间,导致重排。例如,通过 JavaScript 动态修改一个元素的宽度。 - 内容变化:当元素的文本内容发生变化,导致其宽度或高度改变时,也会触发重排。比如,一个
<div>元素中的文本增加或减少,可能会使该<div>的尺寸改变,进而影响周围元素的布局。
重绘
-
定义:当元素的外观发生改变,但布局没有改变时,就会发生重绘。例如,改变元素的颜色、背景色、边框样式等,这些操作只影响元素的绘制,而不会影响其在文档流中的位置和布局。重绘的代价相对重排较小,但仍然会消耗一定的性能。
-
触发重绘的操作:
- 改变元素的颜色:通过 CSS
color属性改变文本颜色,或者使用background - color属性改变元素的背景颜色,会触发重绘。因为这些操作只改变了元素的外观,而不影响其布局。 - 改变元素的边框样式:修改
border - style(如从solid改为dashed)、border - color或border - width等边框相关属性,会导致元素的边框外观改变,从而触发重绘。 - 改变元素的透明度:使用
opacity属性改变元素的透明度,元素的可见性外观发生变化,但布局不受影响,会触发重绘。例如,将一个元素的opacity从1改为0.5,使其变得半透明。 - 改变元素的盒阴影:修改
box - shadow属性,为元素添加、移除或改变盒阴影的样式,会使元素的外观发生变化,触发重绘。
- 改变元素的颜色:通过 CSS
扩展点
- 重排一定会触发重绘,重绘不会触发重排。
- 为了优化性能,应该尽量减少重排和重绘的发生。例如修改样式时一次性修改而不是一次修改一种样式。获取元素属性时也是同样的道理。