什么是 Reflow(重排)?
What is Reflow?
Reflow, also known as layout or reflowing, is a process in which the browser recalculates the positions and sizes of elements in the Document Object Model (DOM) when the structure, size, position, or certain properties of elements change. Reflow is a costly operation because it can affect the layout of the entire page, requiring the browser to re-render parts of or even the entire page.
Reflow(也称为布局或重排)是指当文档对象模型(DOM)中的元素结构、大小、位置或某些属性发生变化时,浏览器重新计算元素的位置和大小的过程。Reflow 是一个代价高昂的操作,因为它可能会影响整个页面的布局,要求浏览器重新渲染页面的部分或全部内容。
1. When Does Reflow Occur?
Reflow 何时发生?
Reflow occurs whenever changes are made to the DOM that affect the layout of the page. This includes actions such as:
- Adding or removing DOM elements
- Changing an element’s size (e.g., width, height, padding, or margin)
- Modifying text content that changes the dimensions of an element
- Adjusting CSS properties like
display
,position
,float
,overflow
, etc. - Resizing the browser window
- Adding or removing stylesheets
- Manipulating the DOM through JavaScript
Reflow 会在对 DOM 进行影响页面布局的更改时发生。这包括以下操作:
- 添加或删除 DOM 元素
- 更改元素的大小(例如,宽度、高度、填充或边距)
- 修改改变元素尺寸的文本内容
- 调整 CSS 属性,如
display
、position
、float
、overflow
等 - 调整浏览器窗口的大小
- 添加或删除样式表
- 通过 JavaScript 操作 DOM
Examples of Actions Causing Reflow
导致 Reflow 的操作示例
// Example 1: Changing the size of an element
document.querySelector('div').style.width = '200px';
// Example 2: Adding a new element to the DOM
let newElement = document.createElement('p');
document.body.appendChild(newElement);
// Example 3: Changing the display property
document.querySelector('div').style.display = 'none';
Explanation:
- In Example 1, changing the width of a
<div>
triggers a reflow because the browser needs to recalculate the layout of the element and possibly other elements around it. - In Example 2, adding a new
<p>
element to the DOM may cause a reflow as the browser has to account for the new element in the layout. - In Example 3, setting the
display
property tonone
removes the element from the layout flow, triggering a reflow to adjust the layout of the remaining elements.
解释:
- 在示例 1中,更改
<div>
的宽度会触发重排,因为浏览器需要重新计算该元素的布局,并可能重新布局其周围的其他元素。 - 在示例 2中,向 DOM 中添加新的
<p>
元素可能会导致重排,因为浏览器必须在布局中考虑新元素。 - 在示例 3中,将
display
属性设置为none
会将该元素从布局流中移除,从而触发重排以调整剩余元素的布局。
2. Why is Reflow Expensive?
为什么 Reflow 是代价高昂的?
Reflow is considered an expensive operation because it involves recalculating the layout of the page, which can be a computationally intensive task. Depending on the scope of the change, reflow can impact not just the element being modified but also its parent, child, and sibling elements, and sometimes even the entire document.
Reflow 被认为是一种代价高昂的操作,因为它涉及到重新计算页面的布局,这可能是一个计算量很大的任务。根据更改的范围,重排可能不仅影响正在修改的元素,还可能影响其父元素、子元素和兄弟元素,有时甚至影响整个文档。
Performance Impact
性能影响
-
Cascading Effects: Changes to the layout of one element can cascade through the DOM tree, causing multiple elements to undergo reflow. This can lead to significant performance degradation, especially on complex pages with many elements.
-
Repaint Trigger: After a reflow, the browser often needs to repaint the affected areas of the screen, which adds additional overhead.
-
Blocking Behavior: Reflow is a blocking operation, meaning that it can cause the browser to temporarily halt other tasks until the reflow is completed, leading to jankiness or delays in user interactions.
-
级联效应:对一个元素布局的更改可能会级联到 DOM 树,导致多个元素经历重排。这可能会导致显著的性能下降,特别是在具有许多元素的复杂页面上。
-
触发重绘:重排后,浏览器通常需要重绘受影响的屏幕区域,这增加了额外的开销。
-
阻塞行为:重排是一种阻塞操作,这意味着它可能会导致浏览器暂时停止其他任务,直到重排完成,从而导致页面卡顿或用户交互延迟。
Example: Cascading Reflow
示例:级联重排
// Changing the width of a parent element
document.querySelector('.parent').style.width = '400px';
Explanation:
- When the width of a parent element is changed, the browser must recalculate the layout for all of its child elements, as their positions and sizes may depend on the parent’s size. This cascading effect can result in a significant performance cost if the parent element has many children.
解释:
- 当父元素的宽度发生变化时,浏览器必须重新计算其所有子元素的布局,因为它们的位置和大小可能依赖于父元素的大小。如果父元素有很多子元素,这种级联效应可能导致显著的性能开销。
3. How to Minimize Reflow
如何最小化 Reflow
To optimize web performance and reduce the impact of reflows, developers should follow best practices that minimize the number and scope of reflows. Some strategies include:
为了优化网页性能并减少重排的影响,开发人员应遵循最佳实践,以最小化重排的数量和范围。以下是一些策略:
1. Batch DOM Changes
批量 DOM 更改
Grouping multiple DOM changes together can reduce the number of reflows. For example, instead of making multiple sequential changes to an element’s style, batch them together so that the browser only needs to reflow once.
将多个 DOM 更改组合在一起可以减少重排的次数。例如,与其对元素的样式进行多次连续更改,不如将它们批量处理,这样浏览器只需重排一次。
// Instead of this:
element.style.width = '100px';
element.style.height = '200px';
element.style.marginTop = '10px';
// Do this:
element.style.cssText = 'width: 100px; height: 200px; margin-top: 10px;';
2. Use class
or id
for Bulk Changes
使用 class
或 id
进行批量更改
Instead of modifying individual styles directly, applying a class
or id
that contains all the style changes can reduce reflows.
与直接修改单个样式相比,应用包含所有样式更改的 class
或 id
可以减少重排。
// Instead of modifying styles one by one:
element.style.display = 'none';
element.style.backgroundColor = 'red';
// Apply a class instead:
element.classList.add('hidden-and-red');
3. Avoid Layout Thrashing
避免布局抖动
Layout thrashing occurs when you repeatedly read and write to the DOM in a way that causes multiple reflows. To avoid this, minimize the number of times you read layout properties (like offsetWidth
, scrollTop
) between DOM writes.
布局抖动发生在您以导致多次重排的方式反复读写 DOM 时。为避免这种情况,应尽量减少在 DOM 写操作之间读取布局属性(如 offsetWidth
、scrollTop
)的次数。
// Bad: Causes layout thrashing
for (let i = 0; i < 100; i++) {
element.style.width = element.offsetWidth + 1 + 'px';
}
// Good: Reduce layout thrashing
let width = element.offsetWidth;
for (let i = 0; i < 100; i++) {
width += 1;
}
element.style.width = width + 'px';
4. Use CSS for Animations
使用 CSS 进行动画
Whenever possible, use CSS transitions or animations instead of JavaScript for animations. CSS animations are handled by the browser’s rendering engine and are often more efficient, as they don’t trigger reflows as frequently as JavaScript-driven animations.
尽可能使用 CSS 过渡或动画而不是 JavaScript 进行动画。CSS 动画由浏览器的渲染引擎处理,通常更高效,因为它们不会像 JavaScript 驱动的动画那样频繁地触发重排
。
/* Example of CSS animation */
.element {
transition: transform 0.3s ease;
}
.element:hover {
transform: scale(1.1);
}
4. Conclusion
结论
Reflow is a crucial part of the browser’s rendering process, but it can also be a significant performance bottleneck if not managed carefully. By understanding what triggers reflow and adopting best practices to minimize it, developers can optimize the performance of their web pages, leading to faster load times and smoother user experiences.
重排是浏览器渲染过程中的一个关键部分,但如果不小心管理,它也可能成为一个重要的性能瓶颈。通过理解触发重排的因素并采取最佳实践来最小化它,开发人员可以优化其网页的性能,从而带来更快的加载时间和更流畅的用户体验。
Leave a Reply