Tìm hiểu cách xác định và khắc phục sự cố thay đổi bố cục.
Ngày xuất bản: 11/3/2021, Ngày cập nhật gần đây nhất: 7/2/2025
Phần đầu tiên của bài viết này thảo luận về công cụ gỡ lỗi thay đổi bố cục, còn phần thứ hai thảo luận về quy trình suy nghĩ cần sử dụng khi xác định nguyên nhân gây ra thay đổi bố cục.
Công cụ
Bạn có thể gỡ lỗi Layout Shifts bằng Layout Instability API hoặc bằng các công cụ như DevTools để tóm tắt dữ liệu từ API này ở định dạng dễ hiểu hơn.
API về sự không ổn định của bố cục
Layout Instability API (API về sự không ổn định của bố cục) là cơ chế trình duyệt để đo lường và báo cáo các thay đổi về bố cục. Tất cả các công cụ để gỡ lỗi thay đổi bố cục, bao gồm cả DevTools, đều được xây dựng dựa trên API Layout Instability (API về sự không ổn định của bố cục). Tuy nhiên, việc sử dụng trực tiếp API Layout Instability là một công cụ gỡ lỗi mạnh mẽ nhờ tính linh hoạt.
Cách sử dụng
Cùng một đoạn mã đo lường Điểm số tổng hợp về mức thay đổi bố cục (CLS) cũng có thể dùng để gỡ lỗi các thay đổi bố cục. Đoạn mã sau đây ghi lại thông tin về các thay đổi bố cục vào bảng điều khiển. Việc kiểm tra nhật ký này sẽ cung cấp cho bạn thông tin về thời điểm, vị trí và cách thức xảy ra sự thay đổi bố cục.
let cls = 0;
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
cls += entry.value;
console.log('Current CLS value:', cls, entry);
}
}
}).observe({type: 'layout-shift', buffered: true});
Khi chạy tập lệnh này, hãy lưu ý rằng:
- Tuỳ chọn
buffered: true
cho biết rằngPerformanceObserver
sẽ kiểm tra vùng đệm mục nhập hiệu suất của trình duyệt để tìm các mục nhập hiệu suất được tạo trước khi khởi chạy trình quan sát. Do đó,PerformanceObserver
sẽ báo cáo các thay đổi về bố cục xảy ra cả trước và sau khi được khởi tạo. Hãy lưu ý điều này khi kiểm tra nhật ký bảng điều khiển. Sự cố ban đầu về việc thay đổi bố cục có thể phản ánh một báo cáo tồn đọng, thay vì sự xuất hiện đột ngột của nhiều thay đổi bố cục. - Để tránh ảnh hưởng đến hiệu suất,
PerformanceObserver
sẽ đợi cho đến khi luồng chính ở trạng thái rảnh để báo cáo về các thay đổi về bố cục. Do đó, tuỳ thuộc vào mức độ bận rộn của luồng chính, có thể có độ trễ nhỏ giữa thời điểm thay đổi bố cục xảy ra và thời điểm thay đổi bố cục được ghi lại trong bảng điều khiển. - Tập lệnh này bỏ qua các thay đổi về bố cục xảy ra trong vòng 500 ms kể từ khi người dùng nhập dữ liệu, do đó không tính vào CLS.
Thông tin về các thay đổi bố cục được báo cáo bằng cách kết hợp hai API: giao diện LayoutShift
và LayoutShiftAttribution
. Mỗi giao diện này được giải thích chi tiết hơn trong các phần sau.
LayoutShift
Mỗi lần thay đổi bố cục sẽ được báo cáo bằng giao diện LayoutShift
. Nội dung của một mục nhập sẽ có dạng như sau:
duration: 0
entryType: "layout-shift"
hadRecentInput: false
lastInputTime: 0
name: ""
sources: (3) [LayoutShiftAttribution, LayoutShiftAttribution, LayoutShiftAttribution]
startTime: 11317.934999999125
value: 0.17508567530168798
Mục trước đó cho biết một sự thay đổi bố cục trong đó 3 phần tử DOM đã thay đổi vị trí. Điểm số về mức thay đổi bố cục của mức thay đổi bố cục cụ thể này là 0.175
.
Đây là các thuộc tính của một thực thể LayoutShift
phù hợp nhất với việc gỡ lỗi các thay đổi về bố cục:
Thuộc tính | Mô tả |
---|---|
sources |
Thuộc tính sources liệt kê các phần tử DOM đã di chuyển trong quá trình thay đổi bố cục. Mảng này có thể chứa tối đa 5 nguồn. Trong trường hợp có nhiều hơn 5 phần tử chịu ảnh hưởng của việc thay đổi bố cục, thì 5 nguồn thay đổi bố cục lớn nhất (được đo lường theo mức tác động đến độ ổn định của bố cục) sẽ được báo cáo. Thông tin này được báo cáo bằng cách sử dụng giao diện LayoutShiftAttribution (được giải thích chi tiết hơn ở bên dưới). |
value |
Thuộc tính value báo cáo điểm số thay đổi bố cục cho một thay đổi bố cục cụ thể. |
hadRecentInput |
Thuộc tính hadRecentInput cho biết liệu có sự thay đổi bố cục nào xảy ra trong vòng 500 mili giây kể từ khi người dùng nhập hay không. |
startTime |
Thuộc tính startTime cho biết thời điểm xảy ra sự thay đổi bố cục. startTime được biểu thị bằng mili giây và được đo lường tương ứng với thời điểm bắt đầu tải trang. |
duration |
Thuộc tính duration sẽ luôn được đặt thành 0 . Thuộc tính này được kế thừa từ giao diện PerformanceEntry (giao diện LayoutShift mở rộng giao diện PerformanceEntry ). Tuy nhiên, khái niệm về thời lượng không áp dụng cho các sự kiện thay đổi bố cục, vì vậy, thời lượng được đặt thành 0 . Để biết thông tin về giao diện PerformanceEntry , hãy tham khảo thông số kỹ thuật. |
LayoutShiftAttribution
Giao diện LayoutShiftAttribution
mô tả một lần dịch chuyển của một phần tử DOM. Nếu nhiều phần tử thay đổi trong quá trình thay đổi bố cục, thì thuộc tính sources
sẽ chứa nhiều mục nhập.
Ví dụ: JSON sau đây tương ứng với một thay đổi bố cục với một nguồn: việc di chuyển xuống dưới của phần tử DOM <div id='banner'>
từ y: 76
đến y:246
.
// ...
"sources": [
{
"node": "div#banner",
"previousRect": {
"x": 311,
"y": 76,
"width": 4,
"height": 18,
"top": 76,
"right": 315,
"bottom": 94,
"left": 311
},
"currentRect": {
"x": 311,
"y": 246,
"width": 4,
"height": 18,
"top": 246,
"right": 315,
"bottom": 264,
"left": 311
}
}
]
Thuộc tính node
xác định phần tử HTML đã dịch chuyển. Khi di chuột qua thuộc tính này trong DevTools, phần tử trang tương ứng sẽ được làm nổi bật.
Các thuộc tính previousRect
và currentRect
báo cáo kích thước và vị trí của nút.
- Toạ độ
x
vày
báo cáo toạ độ x và toạ độ y tương ứng của góc trên cùng bên trái của phần tử - Thuộc tính
width
vàheight
báo cáo chiều rộng và chiều cao tương ứng của phần tử. - Các thuộc tính
top
,right
,bottom
vàleft
báo cáo các giá trị toạ độ x hoặc y tương ứng với cạnh nhất định của phần tử. Nói cách khác, giá trị củatop
bằngy
; giá trị củabottom
bằngy+height
.
Nếu tất cả thuộc tính của previousRect
được đặt thành 0, thì điều này có nghĩa là phần tử đã chuyển sang chế độ xem. Nếu tất cả thuộc tính của currentRect
được đặt thành 0, thì điều này có nghĩa là phần tử đã chuyển ra khỏi khung hiển thị.
Một trong những điều quan trọng nhất cần hiểu khi diễn giải các kết quả này là các phần tử được liệt kê là nguồn là các phần tử đã thay đổi trong quá trình thay đổi bố cục. Tuy nhiên, có thể các phần tử này chỉ liên quan gián tiếp đến "nguyên nhân gốc rễ" của sự bất ổn định bố cục. Dưới đây là một vài ví dụ.
Ví dụ #1
Sự thay đổi bố cục này sẽ được báo cáo bằng một nguồn: phần tử B. Tuy nhiên, nguyên nhân gốc rễ của sự thay đổi bố cục này là do kích thước của phần tử A thay đổi.
Ví dụ 2
Sự thay đổi bố cục trong ví dụ này sẽ được báo cáo bằng hai nguồn: phần tử A và phần tử B. Nguyên nhân gốc rễ của sự thay đổi bố cục này là do thay đổi vị trí của phần tử A.
Ví dụ #3
Sự thay đổi bố cục trong ví dụ này sẽ được báo cáo bằng một nguồn: phần tử B. Việc thay đổi vị trí của phần tử B đã dẫn đến sự thay đổi bố cục này.
Ví dụ #4
Mặc dù phần tử B thay đổi kích thước, nhưng không có sự thay đổi bố cục nào trong ví dụ này.
Công cụ cho nhà phát triển
DevTools có một số công cụ giúp gỡ lỗi các thay đổi về bố cục.
Bảng điều khiển hiệu suất
Chế độ xem chỉ số trực tiếp của Bảng điều khiển hiệu suất cho phép bạn tương tác với trang và theo dõi điểm CLS để xác định những lượt tương tác gây ra sự thay đổi lớn về bố cục.
![Các bản ghi Layout Shift đang hiển thị trong màn hình chỉ số trực tiếp của bảng điều khiển hiệu suất trong Chrome DevTools.](https://web.developers.google.cn/static/articles/debug-layout-shifts/image/live-metrics-cls.png?hl=vi)
Sau khi có thể tái tạo một sự thay đổi bố cục một cách đáng tin cậy, bạn có thể thực hiện theo dõi để biết thêm thông tin chi tiết:
![Các bản ghi Layout Shift (Thay đổi bố cục) đang hiển thị trong bảng điều khiển hiệu suất của Chrome DevTools.](https://web.developers.google.cn/static/articles/debug-layout-shifts/image/devtools-cls-debugging.png?hl=vi)
Layout Shift
. Khi nhấp vào hình kim cương, bạn sẽ thấy ảnh động về sự thay đổi và thông tin chi tiết trong bảng Tóm tắt.
Các thay đổi bố cục được làm nổi bật trong kênh Thay đổi bố cục. Đường màu tím nhóm các ca làm việc thành cụm ca làm việc, trong đó các viên kim cương thể hiện từng ca làm việc trong cụm đó. Kích thước của kim cương tỷ lệ thuận với kích thước của sự thay đổi, cho phép bạn tập trung vào những sự thay đổi lớn nhất.
Khi nhấp vào một ca làm việc, một cửa sổ bật lên sẽ hiển thị ảnh động của ca làm việc đó và đánh dấu phần tử thay đổi bằng màu tím.
Ngoài ra, chế độ xem Tóm tắt cho bản ghi Layout Shift
bao gồm thời gian bắt đầu, điểm dịch chuyển cũng như các phần tử được dịch chuyển. Điều này đặc biệt hữu ích để biết thêm thông tin chi tiết về các vấn đề về CLS tải, vì vấn đề này dễ dàng được tái hiện bằng hồ sơ hiệu suất tải lại.
Thẻ này cũng liên kết đến thông tin chi tiết về Nguyên nhân gây ra sự thay đổi bố cục trong bảng điều khiển Thông tin chi tiết ở bên trái. Bảng này cho thấy tổng CLS ở trên cùng, cũng như các lý do có thể gây ra sự thay đổi bố cục.
Để biết thêm thông tin về cách sử dụng bảng điều khiển Hiệu suất, hãy tham khảo Tài liệu tham khảo về phân tích hiệu suất.
Làm nổi bật khu vực thay đổi bố cục
Việc làm nổi bật các khu vực có thay đổi về bố cục có thể là một kỹ thuật hữu ích để nhanh chóng nắm bắt vị trí và thời điểm xảy ra các thay đổi về bố cục trên một trang.
Để bật Khu vực thay đổi bố cục trong DevTools, hãy chuyển đến Settings (Cài đặt) > More Tools (Công cụ khác) > Rendering (Hiển thị) > Layout Shift Regions (Khu vực thay đổi bố cục), sau đó làm mới trang mà bạn muốn gỡ lỗi. Các khu vực có thay đổi về bố cục sẽ được đánh dấu nhanh bằng màu tím.
Quy trình suy nghĩ để xác định nguyên nhân gây ra sự thay đổi bố cục
Bạn có thể làm theo các bước sau để xác định nguyên nhân gây ra sự thay đổi bố cục, bất kể thời điểm hoặc cách thức thay đổi bố cục. Bạn có thể bổ sung các bước này bằng cách chạy Lighthouse. Tuy nhiên, hãy lưu ý rằng Lighthouse chỉ có thể xác định các thay đổi bố cục xảy ra trong lần tải trang đầu tiên. Ngoài ra, Lighthouse cũng chỉ có thể đưa ra đề xuất cho một số nguyên nhân gây ra sự thay đổi bố cục, ví dụ: các phần tử hình ảnh không có chiều rộng và chiều cao rõ ràng.
Xác định nguyên nhân gây ra sự thay đổi bố cục
Các sự kiện sau có thể gây ra sự thay đổi bố cục:
- Thay đổi vị trí của một phần tử DOM
- Thay đổi kích thước của một phần tử DOM
- Chèn hoặc xoá phần tử DOM
- Ảnh động kích hoạt bố cục
Cụ thể, phần tử DOM ngay trước phần tử bị dịch chuyển là phần tử có nhiều khả năng nhất liên quan đến việc "gây ra" sự thay đổi bố cục. Do đó, khi điều tra lý do xảy ra sự thay đổi bố cục, hãy cân nhắc:
- Vị trí hoặc kích thước của phần tử trước đó có thay đổi không?
- Phần tử DOM có được chèn hoặc xoá trước phần tử bị dịch chuyển không?
- Vị trí của phần tử đã di chuyển có thay đổi rõ ràng không?
Nếu phần tử trước đó không gây ra sự thay đổi bố cục, hãy tiếp tục tìm kiếm bằng cách cân nhắc các phần tử trước và gần đó khác.
Ngoài ra, hướng và khoảng cách của sự thay đổi bố cục có thể cung cấp gợi ý về nguyên nhân gốc rễ. Ví dụ: một sự thay đổi lớn theo chiều hướng xuống thường cho biết việc chèn một phần tử DOM, trong khi sự thay đổi bố cục 1 px hoặc 2 px thường cho biết việc áp dụng các kiểu CSS xung đột hoặc việc tải và áp dụng phông chữ web.
![Sơ đồ cho thấy sự thay đổi bố cục do hoán đổi phông chữ](https://web.developers.google.cn/static/articles/debug-layout-shifts/image/diagram-showing-layout-s-60ec3d8c95616.png?hl=vi)
Sau đây là một số hành vi cụ thể thường xuyên gây ra sự kiện thay đổi bố cục:
Thay đổi vị trí của một phần tử (không phải do chuyển động của một phần tử khác)
Loại thay đổi này thường là kết quả của:
- Các trang kiểu được tải muộn hoặc ghi đè các kiểu đã khai báo trước đó.
- Ảnh động và hiệu ứng chuyển đổi.
Thay đổi kích thước của một phần tử
Loại thay đổi này thường là kết quả của:
- Các trang kiểu được tải muộn hoặc ghi đè các kiểu đã khai báo trước đó.
- Hình ảnh và iframe không có thuộc tính
width
vàheight
sẽ tải sau khi "khe" của chúng được hiển thị. - Các khối văn bản không có thuộc tính
width
hoặcheight
sẽ hoán đổi phông chữ sau khi văn bản được hiển thị.
Việc chèn hoặc xoá các phần tử DOM
Điều này thường là do:
- Việc chèn quảng cáo và các nội dung nhúng khác của bên thứ ba.
- Chèn biểu ngữ, cảnh báo và cửa sổ bật lên.
- Cuộn vô hạn và các mẫu trải nghiệm người dùng khác tải nội dung bổ sung lên trên nội dung hiện có.
Ảnh động kích hoạt bố cục
Một số hiệu ứng ảnh động có thể kích hoạt bố cục. Một ví dụ phổ biến về điều này là khi các phần tử DOM được "tạo ảnh động" bằng cách tăng các thuộc tính như top
hoặc left
thay vì sử dụng thuộc tính transform
của CSS. Hãy đọc bài viết Cách tạo ảnh động CSS hiệu suất cao để biết thêm thông tin.
Tái tạo sự thay đổi bố cục
Bạn không thể khắc phục các thay đổi về bố cục mà bạn không thể tái tạo. Một trong những việc đơn giản nhất nhưng hiệu quả nhất mà bạn có thể làm để hiểu rõ hơn về độ ổn định của bố cục trang web là dành 5 đến 10 phút để tương tác với trang web của bạn với mục tiêu kích hoạt các thay đổi về bố cục. Hãy giữ cho bảng điều khiển luôn mở trong khi thực hiện việc này và sử dụng API Layout Instability (API về sự không ổn định của bố cục) để báo cáo về các thay đổi bố cục.
Đối với những thay đổi về bố cục khó xác định, hãy cân nhắc lặp lại bài tập này với nhiều thiết bị và tốc độ kết nối. Cụ thể, việc sử dụng tốc độ kết nối chậm hơn có thể giúp bạn dễ dàng xác định các thay đổi về bố cục. Ngoài ra, bạn có thể sử dụng câu lệnh debugger
để dễ dàng chuyển đổi bố cục.
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
cls += entry.value;
debugger;
console.log('Current CLS value:', cls, entry);
}
}
}).observe({type: 'layout-shift', buffered: true});
Cuối cùng, đối với các vấn đề về bố cục không thể tái hiện trong quá trình phát triển, hãy cân nhắc sử dụng Layout Instability API (API về sự không ổn định của bố cục) cùng với công cụ ghi nhật ký giao diện người dùng mà bạn chọn để thu thập thêm thông tin về các vấn đề này. Hãy xem mã ví dụ về cách theo dõi phần tử bị dịch chuyển lớn nhất trên một trang.