CSS 回流(Reflow)和重绘(Repaint)
基本概念
回流(Reflow) 和 重绘(Repaint) 是浏览器渲染过程中的两个重要概念,它们会影响页面性能。
回流(Reflow)
也称为"布局"(Layout)
当渲染树中的一部分或全部因为元素的规模尺寸、布局、隐藏等改变而需要重新构建时发生
会计算所有受影响元素的几何属性(位置和大小)
是开销较大的操作
重绘(Repaint)
当元素的外观样式改变但不影响布局时发生(如颜色、背景色等)
不需要重新计算几何属性
开销相对较小
触发条件
触发回流的操作
页面首次渲染
浏览器窗口大小改变
元素尺寸或位置改变(width, height, margin, padding, border等)
元素内容变化(文字数量、图片大小等)
添加/删除可见DOM元素
激活CSS伪类(:hover等)
查询某些属性或调用某些方法(见下文)
触发重绘的操作
颜色、背景色等不影响布局的样式变化
visibility样式的改变(但display:none会触发回流)
性能影响
回流比重绘的代价更高,因为它会导致浏览器重新计算所有受影响元素的几何属性,并可能导致部分或整个渲染树需要重新构建。
优化建议
避免频繁操作样式:最好一次性修改样式,而不是多次修改
// 不好 el.style.margin = '5px'; el.style.padding = '10px';// 更好 el.style.cssText = 'margin:5px; padding:10px;';
使用文档片段(DocumentFragment):批量操作DOM
const fragment = document.createDocumentFragment(); // 添加多个元素到fragment document.body.appendChild(fragment);
避免强制同步布局:不要在读取布局属性前修改样式
// 不好 - 强制同步布局 const width = el.offsetWidth; el.style.width = width + 10 + 'px';// 更好 - 先修改后读取 el.style.width = '100px'; const width = el.offsetWidth;
使用transform和opacity:这些属性不会触发回流
避免table布局:table中一个小改动可能导致整个table回流
CSS优化:
避免多层内联样式
将动画元素设置为position: absolute/fixed
避免CSS表达式
常见触发回流的属性和方法
属性(读取时会强制回流)
offsetTop/offsetLeft/offsetWidth/offsetHeight
scrollTop/scrollLeft/scrollWidth/scrollHeight
clientTop/clientLeft/clientWidth/clientHeight
getComputedStyle()
getBoundingClientRect()
方法(可能触发回流)
elem.append()
elem.remove()
elem.insertBefore()
elem.replaceChild()
elem.style.setProperty()
window.getComputedStyle()
elem.scrollIntoView()
elem.focus()
理解回流和重绘有助于开发者编写更高效的CSS和JavaScript代码,提升页面性能。