Blogs
Reflow, Repaint, Layout Shift là gì? Tối ưu để tránh CLS cao trong Core Web Vitals

Reflow, Repaint, Layout Shift là gì? Tối ưu để tránh CLS cao trong Core Web Vitals

Tìm hiểu về Reflow, Repaint và Layout Shift – ba khái niệm quan trọng ảnh hưởng đến trải nghiệm người dùng và điểm Core Web Vitals của trang web bạn.

Vì sao bạn cần hiểu Reflow, Repaint và Layout Shift?

Khi xây dựng giao diện web, đặc biệt là các ứng dụng SPA hay các trang thương mại điện tử, bạn thường tối ưu hình ảnh, bundle nhỏ gọn, code chia nhỏ... Nhưng có một thứ tinh tế mà đôi khi chúng ta bỏ qua: trải nghiệm người dùng khi trang đang render.

Các hiện tượng như:

  • Giao diện bị “nhảy” khi ảnh vừa tải xong
  • Văn bản tự động bị đẩy xuống vì banner xuất hiện chậm
  • Người dùng định click thì nút trượt sang chỗ khác

Tất cả đều liên quan đến Reflow, Repaint, và Layout Shift. Và những điều này ảnh hưởng trực tiếp đến CLS – Cumulative Layout Shift, một chỉ số quan trọng trong Core Web Vitals của Google.


Reflow là gì?

Reflow (hay còn gọi là Layout) là quá trình trình duyệt tính toán lại kích thước và vị trí của các phần tử trên trang.

Reflow xảy ra khi:

  • Thêm, xóa hoặc thay đổi phần tử DOM
  • Thay đổi các thuộc tính CSS như width, font-size, position, display...
  • Thay đổi nội dung text
  • Kích thước cửa sổ trình duyệt thay đổi (resize)

Ví dụ:

element.style.width = "200px";

Thao tác này yêu cầu trình duyệt tính toán lại bố cục các phần tử liên quan – đó chính là Reflow.

Reflow rất tốn kém tài nguyên. Một thay đổi nhỏ có thể ảnh hưởng đến nhiều phần tử, đặc biệt trong layout phức tạp.


Repaint là gì?

Repaint là quá trình vẽ lại phần tử trên màn hình mà không cần tính toán lại layout.

Repaint xảy ra khi:

  • Thay đổi màu sắc (background-color, color)
  • Thay đổi visibility
  • Đổ bóng, viền, opacity…

Ví dụ:

element.style.backgroundColor = "blue";

Không cần tính lại bố cục, chỉ cần tô lại màu => Repaint.

So với Reflow, Repaint nhẹ hơn. Tuy nhiên nếu diễn ra liên tục (ví dụ animation không tối ưu), vẫn gây drop FPS và lag.


Layout Shift là gì?

Layout Shift xảy ra khi một phần tử bất ngờ thay đổi vị trí trên màn hình mà người dùng không tương tác gì cả. Khi điều này xảy ra quá nhiều hoặc quá trễ, trải nghiệm người dùng sẽ bị ảnh hưởng mạnh mẽ.

Đây chính là thứ mà CLS – Cumulative Layout Shift đo lường.

Một số nguyên nhân phổ biến:

  • Ảnh chưa có kích thước trước khi tải => ảnh “đẩy” phần tử khác xuống
  • Font hiển thị muộn => văn bản bị dịch chuyển (FOIT/FOUT)
  • Quảng cáo, popup render trễ => đẩy nội dung đi
  • Sử dụng JavaScript thêm nội dung bất ngờ vào DOM

Cách đo CLS (Cumulative Layout Shift)

CLS đo bằng công thức:

CLS = Tổng Layout Shift Score = Impact Fraction * Distance Fraction

Nói đơn giản:

  • Impact Fraction: bao nhiêu phần trăm vùng màn hình bị thay đổi
  • Distance Fraction: khoảng cách phần tử đã bị dịch chuyển bao nhiêu

Google khuyến nghị: CLS < 0.1 để đạt tiêu chuẩn tốt cho Core Web Vitals.


Cách giảm Reflow và Repaint không cần thiết

  1. Tránh thao tác DOM liên tục
// KHÔNG nên for (let i = 0; i < 100; i++) { document.body.style.margin = `${i}px`; } // NÊN document.body.style.margin = "100px";
  1. Dùng class thay vì thay đổi style trực tiếp
element.classList.add("expanded"); // Gọn hơn, dễ maintain
  1. Đọc và ghi DOM riêng biệt
const height = element.offsetHeight; // Đọc layout element.style.height = height + 10 + "px"; // Ghi layout // Gộp nhiều thay đổi vào cùng một frame requestAnimationFrame(() => { // Thay đổi nhiều thứ tại đây });

Cách tối ưu để tránh CLS cao

1. Luôn đặt chiều cao cố định cho ảnh

<img src="/logo.png" width="200" height="100" alt="Logo" />

Hoặc dùng CSS:

img { aspect-ratio: 2 / 1; }

Next.js dùng next/image sẽ tự động xử lý việc này.


2. Tránh font nhảy – preload font sớm

<link rel="preload" href="/fonts/custom.woff2" as="font" type="font/woff2" crossorigin="anonymous" />

Hoặc dùng font-display: swap để tránh chặn render quá lâu.


3. Đặt chỗ sẵn cho component động (banner, quảng cáo...)

Nếu biết chiều cao của một thành phần sẽ xuất hiện muộn, hãy dành sẵn khoảng trống trong layout:

.banner-placeholder { min-height: 120px; }

4. Tránh chèn DOM bất ngờ từ JS

Hạn chế setTimeout để render component động sau vài giây. Nếu cần animation, dùng opacity, transform để transition mượt mà mà không gây layout shift.


Tổng kết

Reflow, Repaint và Layout Shift là ba yếu tố quan trọng ảnh hưởng trực tiếp đến trải nghiệm người dùng – và đặc biệt là chỉ số CLS trong Core Web Vitals.

Việc hiểu cách trình duyệt hoạt động giúp bạn:

  • Tối ưu hiệu suất mà không cần chỉ nhìn vào Lighthouse
  • Tránh “trượt điểm” SEO vì lỗi UX
  • Làm chủ frontend một cách chuyên nghiệp hơn

Hãy bắt đầu tối ưu từ những điều nhỏ: đặt kích thước ảnh, preload font, tránh layout shift không cần thiết. Dần dần, bạn sẽ thấy trang web mượt mà hơn, nhanh hơn – và người dùng hài lòng hơn.

What are Reflow, Repaint, and Layout Shift? Optimizing to Reduce CLS in Core Web Vitals

Understand the critical rendering concepts of Reflow, Repaint, and Layout Shift that impact web performance and how to minimize CLS.

Why should you understand Reflow, Repaint, and Layout Shift?

When building a website UI—especially in modern SPAs or e-commerce pages—you might already optimize images, split your code, lazy load, or minify scripts. But there's one subtle yet crucial aspect many developers overlook: how stable and smooth the page appears while rendering.

You may have seen things like:

  • The layout “jumps” after an image finishes loading
  • A block of text suddenly moves down because of a late banner
  • A button shifts right when the user is just about to click it

All of these are related to Reflow, Repaint, and Layout Shift. These behaviors directly impact CLS – Cumulative Layout Shift, one of the key metrics in Google’s Core Web Vitals.


What is Reflow?

Reflow (also called Layout) is when the browser recalculates the size and position of elements on the page.

Reflow is triggered when:

  • A DOM element is added, removed, or modified
  • CSS properties like width, font-size, position, display, etc. are changed
  • Text content is updated
  • The browser window is resized

For example:

element.style.width = "200px";

This forces the browser to recalculate the layout for that element and potentially for its siblings, parent, or children—hence, a reflow.

Reflow is resource-intensive. A small change can cascade and affect many parts of the layout, especially in complex structures.


What is Repaint?

Repaint is when the browser redraws elements visually without recalculating their layout.

Repaint happens when:

  • You change styles like background-color, color, border, or visibility
  • You apply shadow effects, opacity changes, etc.

Example:

element.style.backgroundColor = "blue";

No layout change needed, just visual re-rendering.

Repaint is less expensive than Reflow, but if triggered repeatedly (e.g., through poorly optimized animations), it can still hurt performance.


What is Layout Shift?

Layout Shift refers to elements unexpectedly moving on the screen without user interaction. If this happens too often or too late in the load process, it can lead to a very poor user experience.

This is exactly what CLS – Cumulative Layout Shift measures.

Common causes:

  • Images that load without predefined dimensions
  • Custom fonts replacing fallback fonts (FOIT/FOUT)
  • Late-loaded ads or banners pushing content around
  • JavaScript injecting DOM elements dynamically without space reservations

How is CLS calculated?

CLS is determined by this formula:

CLS = Total Layout Shift Score = Impact Fraction × Distance Fraction

Simply put:

  • Impact Fraction: how much of the screen is affected by the shift
  • Distance Fraction: how far the shifted elements move

Google recommends keeping CLS below 0.1 for good Core Web Vitals.


How to reduce unnecessary Reflows and Repaints

  1. Avoid continuous DOM manipulations
// NOT recommended for (let i = 0; i < 100; i++) { document.body.style.margin = `${i}px`; } // Recommended document.body.style.margin = "100px";
  1. Use CSS classes instead of inline styles
element.classList.add("expanded");
  1. Read and write DOM separately
const height = element.offsetHeight; // Read layout element.style.height = height + 10 + "px"; // Write layout // Better: batch DOM updates in requestAnimationFrame requestAnimationFrame(() => { // Make multiple changes here });

How to optimize and reduce CLS

1. Always set fixed dimensions for images

<img src="/logo.png" width="200" height="100" alt="Logo" />

Or use CSS:

img { aspect-ratio: 2 / 1; }

If you’re using Next.js, the next/image component does this automatically.


2. Prevent font swap shifts – preload fonts early

<link rel="preload" href="/fonts/custom.woff2" as="font" type="font/woff2" crossorigin="anonymous" />

Or use:

font-display: swap;

This avoids layout-blocking and reduces font-related shifts.


3. Reserve space for dynamic components (banners, ads...)

If a component is going to appear late (e.g., a newsletter banner), reserve its space upfront:

.banner-placeholder { min-height: 120px; }

4. Avoid unexpected DOM insertions via JavaScript

Avoid using setTimeout to inject large UI blocks without prior layout preparation.
If animations are necessary, prefer opacity or transform, which don’t cause layout recalculations.


Conclusion

Reflow, Repaint, and Layout Shift are fundamental to understanding how your page behaves during render—and directly affect CLS, a major Core Web Vital.

By learning how the browser processes your layout, you can:

  • Optimize performance beyond Lighthouse scores
  • Prevent frustrating user experiences
  • Build more stable and professional frontend interfaces

Start with the small things: define image sizes, preload fonts, and reserve layout space. Over time, your pages will load smoother, feel faster, and earn better trust from your users.

Tag

Buy Me A Coffee
    Performance