重排
重排 (Reflow) 是指当 DOM 的修改影响了元素的几何属性(位置、尺寸)时,浏览器需要重新排布元素在页面上的几何布局,这个过程称为重排。
重绘
重绘 (Repaint) 是指当 DOM 的修改只影响了元素的外观,而没有影响其布局时,浏览器会跳过布局计算,直接重新绘制元素受影响的部分。
重排一定会引起重绘
哪些操作会引起重排(Repaint)?
1. 页面首次渲染
这是不可避免的第一次重排。
2. DOM 节点的操作
- 添加或删除可见的 DOM 节点(例如 appendChild, removeChild, innerHTML)。
- 改变元素内容,例如修改文本内容或图片尺寸,导致元素尺寸变化。
3. 元素尺寸或位置的改变
- 修改 width, height, margin, padding, border 等。
- 修改 position, top, left, right, bottom 等。
- 修改 display, float, flex, grid 等布局属性。
4. CSS 伪类激活
- 例如 :hover 状态可能会改变元素的尺寸。
5. 字体变化
- 修改 font-size, font-family 等,因为不同字体或字号会占据不同的空间。
6. 浏览器窗口尺寸变化(resize)
- 这会导致整个页面的重排。
7. 获取特定的布局信息(强制重排)
这是一个非常关键的性能陷阱!当你使用 JavaScript 获取某些需要实时计算的布局属性时,浏览器为了返回一个准确的值,会强制立即执行待处理的渲染队列,从而触发重排。
常见的强制重排属性和方法包括:
- offsetTop, offsetLeft, offsetWidth, offsetHeight
- scrollTop, scrollLeft, scrollWidth, scrollHeight
- clientTop, clientLeft, clientWidth, clientHeight
- getComputedStyle()
getComputedStyle() 它返回一个包含元素所有 CSS 样式属性及其最终值的对象。
- getBoundingClientRect()
getBoundingClientRect() 这个对象提供了一组描述该元素
尺寸和在视口(Viewport)中位置的只读属性。
offsetParent:子元素相对谁进行位移
offsetTop:元素上边缘到 offsetParent 上边缘的距离offsetLeft:元素左边缘到 offsetParent 左边缘的距离offsetWidth:元素宽度(内容 + 内边距 + 边框 + 垂直滚动条)offsetHeight:元素高度(内容 + 内边距 + 边框 + 水平滚动条)
client 系列:元素的可视区域尺寸
作用:获取元素可视区域的尺寸(不含滚动条和边框,包含内边距)。
clientTop:上边框宽度(像素)clientLeft:左边框宽度(像素)clientWidth:可视宽度(内容 + 内边距,不含边框和滚动条)clientHeight:可视高度(内容 + 内边距,不含边框和滚动条)
scroll 系列:元素的滚动相关属性(容器的滚动属性)scroll是针对容器的
作用:获取元素的滚动信息和内容总尺寸(包含可滚动的隐藏部分)。
scrollTop:子元素相对容器元素向上滚动的像素数(可读可写)scrollLeft:子元素相对容器元素向左滚动的像素数(可读可写)scrollWidth:容器元素内容总宽度(包含隐藏部分,无滚动条时等于 clientWidth)
针对容器:内容宽度 + 左右内边距(padding-left + padding-right)
scrollHeight:容器元素内容总高度(包含隐藏部分,无滚动条时等于 clientHeight)
哪些操作会引起重绘(Repaint)?
这些操作不影响元素的几何属性,只会改变外观:
- color
- background-color, background-image
- text-decoration
- box-shadow, border-radius
- outline
- visibility: hidden (注意:它只触发重绘,而 display: none 会触发重排)
visibility: hidden 元素依然在文档流中,只是不可见
display: none 元素会从文档流中消失,会引发重绘和重排