什么是浏览器的重排(reflow)和重绘 (repaint)?如何减少重排和重绘?

本文详细介绍了网页渲染的基本过程,包括DOM树与渲染树的生成、重排与重绘的概念及影响因素,并提供了一些优化建议。

一个页面由两部分组成:
DOM:描述该页面的结构
render:描述 DOM 节点 (nodes) 在页面上如何呈现

当 DOM 元素的属性发生变化 (如 color) 时, 浏览器会通知 render 重新描绘相应的元素, 此过程称为 repaint。

如果该次变化涉及元素布局 (如 width), 浏览器则抛弃原有属性, 重新计算并把结果传递给 render 以重新描绘页面元素, 此过程称为 reflow。

这两个过程是很耗费浏览器性能的, 从 IE 系列和 Chrome 渲染页面速度上的差距即可看出渲染引擎计算对应值和呈现并不一定高效, 而每次对元素的操作都会发生 repaints 或 reflow, 因此编写 DOM 交互时如果不注意就会导致页面性能低下.
页面渲染的过程如下:

1.解析HTML代码并生成一个 DOM 树。

2.解析CSS文件,顺序为:浏览器默认样式->自定义样式->页面内的样式。

3.生成一个渲染树(render tree)。这个渲染树和DOM树的不同之处在于,它是受样式影响的。它不包括那些不可见的节点。

4.当渲染树生成之后,浏览器就会在屏幕上“画”出所有渲染树中的节点。


不管页面发生了重绘还是重排,它们都会影响性能(最可怕的是重排 ,应尽量避免) 

下列情况会发生重排

  • 页面初始渲染
  • 添加/删除可见DOM元素
  • 改变元素位置
  • 改变元素尺寸(宽、高、内外边距、边框等)
  • 改变元素内容(文本或图片等)
  • 改变窗口尺寸

怎么减少重排?说一下我的方法:


1.分离读写操作

var curLeft=div.offsetLeft;

var curTop=div.offsetTop;

div.style.left=curLeft+1+'px';

div.style.top=curTop+1+'px';


2.样式集中改变 

可以添加一个类,样式都在类中改变

3.可以使用absolute脱离文档流。

4.使用 display:none ,不使用 visibility,也不要改变 它的 z-index

5.能用css3实现的就用css3实现。


如何在浏览器中查看页面渲染时间


1.打开开发者工具:点击TimeLine 左侧有个小圆点 点击刷新页面会录制整个页面加载出来 时间的分配情况。如下图

下面具体的说一下这几个过程:点击 Event Log :单独勾选Loading项会显示html 和 css 加载时间。如下图:

解析完DOM+css之后会生成一个渲染树 Render Tree,就是 dom 和 css 的一一对应关系。

DOM+css= Render Tree 

layout:  重排 ,又叫回流。

paint:重绘 也可以在Event Log里看的到,这里就不附图了。

重排重绘这些步骤都是在cpu中发生的。

最后 到  compostite Layers阶段,cpu 把生成的 BitMap(位图)传输到GPU,渲染到屏幕。 css3就是在GPU发生的:transform  opacity。

在 GPU发生的属性比较高效。所以css3性能比较高。

小结:

渲染的三个阶段 Layout ,Paint,Composite Layers。

修改不同的css属性会触发不同阶段。

触发的阶段越前,渲染的代价越高。


详解css属性在哪个阶段发生的 参考:https://csstriggers.com

### 什么是浏览器重排? 在网页渲染过程中,**重排reflow)** 是指浏览器新计算页面中 DOM 元素的位置几何信息,并更新渲染树的过程。任何影响元素布局的操作都会触发重排,例如修改元素的尺寸、位置、内容或字体大小等 [^3]。重排是一个相对昂贵的操作,因为它可能会影响到整个页面的布局结构,尤其是当根节点发生改变时。 而**repaint)** 则是在不改变元素布局的前提下,仅对元素的外观进行更新,比如更改背景颜色、字体颜色、可见性等非几何属性 [^1]。通常发生在重排之后,但并非所有都会伴随重排。 --- ### 浏览器渲染流程 浏览器在接收到 HTML CSS 资源后,会依次完成以下步骤: 1. **HTML 解析生成 DOM 树** 2. **CSS 解析生成 CSS 规则** 3. **DOM CSSOM 合并生成渲染树** 4. **排列(Layout):计算每个元素在页面中的具体位置** 5. **制(Painting):将元素制到屏幕上** 其中,**排列对应的是重排制对应的是** [^4]。 --- ### 常见触发重排/的行为 以下行为会触发重排: - 页面首次加载 - 添加或删除可见的 DOM 元素 - 元素位置或尺寸的变化(如 `width`、`height`、`margin` 等) - 内容变化(如文本或图片引起的尺寸变化) - 字体大小变化 - 浏览器窗口大小调整(触发 `resize` 事件) - 使用 JavaScript 动态设置 `style` 属性 [^3] 以下行为只会触发: - 修改非几何属性,如 `color`、`background-color`、`outline`、`visibility` 等 [^1] --- ### 如何优化重排? 为了提高网页性能,可以采取以下策略来减少重排的发生频率及影响范围: #### 1. 减少重排范围 应尽量以局部布局的方式组织 HTML 结构,避免对整个文档树造成影响。这样即使发生重排,也只会影响部分区域 [^3]。 #### 2. 避免频繁操作 DOM 频繁地读取写入 DOM 会导致多次重排。可以使用以下方式优化: - 批量操作 DOM,先将元素从文档中移除,完成所有修改后再插入。 - 使用 `DocumentFragment` 来构建复杂的 DOM 片段后再插入。 #### 3. 使用 `CSS3` 硬件加速 某些 CSS 属性(如 `transform`、`opacity`、`filters` `will-change`)能够触发 GPU 加速,从而避免引起重排。这在动画效果中尤为有效 [^5]。 ```css .element { transform: translateZ(0); will-change: transform; } ``` 但需要注意,过度使用硬件加速可能导致内存占用过高,甚至影响字体渲染质量。 #### 4. 使用防抖节流技术 对于频繁触发的事件(如 `resize`、`scroll`),可以通过防抖(debounce)节流(throttle)控制执行频率,减少不必要的重排。 ```javascript function debounce(fn, delay) { let timer; return function () { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, arguments), delay); }; } window.addEventListener('resize', debounce(() => { // 处理 resize 逻辑 }, 300)); ``` #### 5. 避免强制同步布局 JavaScript 中某些操作会强制浏览器立即执行重排,如访问 `offsetWidth`、`offsetHeight` 等属性。应尽量避免在循环或高频函数中使用这些方法。 --- ### 总结 重排浏览器渲染过程中的关键环节,直接影响网页性能。通过合理使用 CSS 技术、减少 DOM 操作频率以及优化事件处理机制,可以显著提升页面响应速度与用户体验。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值