Đã bao giờ bạn đang đọc một bài báo và bất ngờ một nội dung khác bất ngờ xuất hiện đẩy nội dung bạn đang đọc xuống. Việc các phần tử của trang thay đổi trong khi người dùng đang cố gắng tương tác với trang là một trải nghiệm kém. Thông thường, những trải nghiệm như vậy chỉ gây khó chịu, nhưng trong một số trường hợp, chúng có thể gây ra thiệt hại thực sự như doanh thu. Trong bài này, tôi sẽ giới thiệu với các bạn về số liệu Dịch chuyển bố cục tích lũy (CLS), một chỉ số giúp bạn đo lường và đưa ra báo cáo chính xác về các vấn đề về thay đổi bố cục trên website. Từ đó bạn biết được nguyên nhân cốt lõi gây ra vấn đề này và đi vào xử lý chúng.
Chỉ số CLS là gì ?
Cumulative Layout Shift là một chỉ số quan trọng đo độ ổn định và mức thay đổi bố cục bất ngờ của nội dung trang hiển thị trong suốt quá trình tải.
Trang web có trải nghiệm người dùng tốt là trang web có điểm CLS dưới 0,1. Nếu ít nhất 75 % các trang của một website đáp ứng ngưỡng CLS tốt, thì trang web đó được phân loại hiệu suất CLS tốt.
Lưu ý rằng thay đổi bố cục chỉ xảy ra khi các phần tử thay đổi vị trí bắt đầu của chúng. Nếu một phần tử mới được thêm vào DOM hoặc việc một phần thay đổi kích thước nhưng không dẫn đến các phần tử khác thay đổi vị trí, thì nó không được tính là sự thay đổi bố cục.
Dưới đây là ví dụ:
Những sự thay đổi không mong muốn của nội dung trang thường xảy ra do tài nguyên được tải không đồng bộ, hoặc các phần tử DOM được thêm động (dynamic) vào trang phía trên nội dung hiện có. Nguyên nhân có thể là hình ảnh hoặc video có kích thước không xác định, phông chữ hiển thị lớn hơn hoặc nhỏ hơn so với dự tính hoặc quảng cáo hoặc tiện ích của bên thứ ba tự động thay đổi kích thước.
Cách kiểm tra sự thay đổi bố cục
Cách thứ nhất
Di chuyển đến tab Performance trong Chrome DevTool. Sau đó nhấp vào “Start Profiling and Reload Page”. Nó sẽ làm mới trang và cung cấp cho bạn một báo cáo về hiệu suất của trang web. Tiếp theo bạn nhấn vào “Experience”, trong đó, bạn chọn “Layout Shift” để xem các phần tử gây ra vấn đề này, hoặc bạn có thể tìm kiếm cụm từ “Layout Shift” để dễ thấy kết quả hơn.
Cách thứ hai
Di chuyển đến Lighthouse tab, sau đó nhấn Generate report
Sau khi báo cáo được tạo, bạn tìm đến phần Avoid large layout shifts trong mục Diagnostics, ở đây chỉ ra các phần tử gây ra vấn đề CLS.
Hoặc mục Image elements do not have explicit width
and height
( hình ảnh không có height và width cụ thể)
Các nguyên nhân phổ biến nhất dẫn đến chỉ số CLS kém
Để website của bạn có thể đạt chỉ số CLS cao, trước tiên bạn cần biết được các nguyên nhân cốt lõi gây ra vấn đề này. Những nguyên nhân phổ biến tôi sẽ liệt kê cho bạn như sau:
- Hình ảnh không có kích thước
- Mã nhúng và iframe không có kích thước
- Cách load phông chữ gây ra vấn đề về FOIT / FOUT
- Các nội dụng động
- Tốc độ trang web
- Animations
Các cách xử lý giúp cải thiện điểm số CLS
Hình ảnh không có kích thước
Nguyên nhân
Hình ảnh không có kích thước là những hình ảnh không có thông số kỹ thuật về chiều rộng và chiều cao. Khi bạn truy cập một trang web mà các hình ảnh không có kích thước như vậy, trình duyệt sẽ không dành bất kỳ khoảng không gian nào cho những hình ảnh đó. Vì hình ảnh có kích thước lớn hơn HTML và CSS nên chúng được tải sau. Và một khi hình ảnh được tải, chúng sẽ đẩy nội dung dưới nó khỏi vị trí ban đầu gây ra sự thay đổi bố cục.
Giải pháp
Vì vậy giải pháp cho bạn là định nghĩa giá trị các thuộc tính width
và height
trên các phần tử hình ảnh và video. Cách tiếp cận này đảm bảo rằng trình duyệt có thể phân bổ không gian chính xác cho các phần tử trước khi hình ảnh được tải.
Để xác định các ảnh thiếu kích thước bạn dùng công cụ Lighthouse (cách đo tôi đã nói phía trên).
Tiếp theo bạn tìm các hình ảnh đó trong source code và thêm thuộc tính width
và height
cho ảnh.
<img src="puppy.jpg" width="640" height="360" alt="Puppy with balloons" />
Ở đây width với height tương ứng với chiều rộng và chiều cao của ảnh. Khi thiết kế ảnh thì nên chọn xuất ảnh theo một trong hai tỉ lệ khung hình phổ biến là (16:9 hoặc 4:3). Trong ví dụ trên, 640:360 tương ứng với tỉ lệ ảnh 16:9.
Style mặc định của browser sẽ tính toán aspect-ratio (tỉ lệ khung hình của ảnh) dựa vào thuộc tính width
và height
. Điều này giúp tạo một placeholder (một khoảng không gian có kích thước xác định) trong quá trình tải ảnh. Đoạn code sau có sẵn trong đa số các trình duyệt, bạn không cần thêm:
img {
aspect-ratio: attr(width) / attr(height);
}
Nếu hình ảnh của bạn nằm trong một container. Bạn có thể sử dụng CSS width: 100%;
để thay đổi kích thước hình ảnh theo chiều rộng của container chứa nó. Đặt giá trị height: auto;
để tránh chiều cao hình ảnh là một giá trị cố định (ví dụ: 360px). Như vậy, hình ảnh responsive trên mọi màn hình mà vẫn giữ đúng tỉ lệ, không bị méo.
img {
height: auto;
width: 100%;
}
Hiểu cách trình duyệt xác định trước kích thước của hình ảnh
Ví dụ, khi ảnh của bạn nằm trong một container full-width trên thiết bị có độ rộng 768px. Trong quá trình tải, trình duyệt sẽ tính toán placeholder cho ảnh đó như sau:
Tỉ lệ ảnh là 640:360 tương đương tỉ lệ 16:9.
Ảnh được style width:100%
, vậy chiều rộng là 375px.
Chiều cao tính bằng công thức 768 * (9 / 16) = 432.
Từ đó trình duyệt tạo một placeholder có kích thước 768 x 432 (px), để tránh sự thay đổi bố cục đột ngột.
Các vấn đề FOUT/FOIT của font (phông chữ)
Nguyên nhân
Không quá ngạc nhiên, font là một trong những lý do hàng đầu gây ra các vấn đề về tốc độ trang, bao gồm cả điểm CLS.
Hầu như tất cả các trang web ngày nay đều sử dụng ít nhất một phông chữ custom (phông chữ từ Google Fonts hoặc các nguồn khác). Và vì những phông chữ đó có kích thước và khoảng cách khác với phông chữ trình duyệt mặc định, khi phông chữ custom được tải xong, nó sẽ gây ra sự thay đổi bố cục trên toàn bộ trang web.
Quá trình tải và hiển thị có thể gây ra vấn đề CLS theo hai cách sau:
- Trong quá trình tải, văn vản sẽ hiển thị theo phông chữ mặc định của trình duyệt và đổi lại thành phông chữ custom khi tải xong, gây ra hiện tượng FOUT – flash of unstyled text
- Chữ bị ẩn đi cho đến khi font chữ custom được tải xong, gây ra hiện tượng FOIT – flash of invisible text
Giải pháp
Nếu các tập tin fonts được host trực tiếp trên server, bạn có thể tải trước font sử dụng thuộc tính rel="preload"
.
Trong báo cáo Lighthouse, tìm đến mục Maximum critical path latency
Tại đây tập tin Pacifico-Bold.woff2 nằm cuối cùng trong chuỗi request quan trọng, nên nó cần được tải trước như sau:
<link rel="preload" href="/assets/Pacifico-Bold.woff2" as="font" type="font/woff2" crossorigin>
Lưu ý: Nếu tệp Pacifico.woff2 không được sử dụng để style trong khung hình đầu tiên thì không cần tải trước tập tin này.
Ngoài ra, để giúp quá trình tải font nhanh hơn bạn có thể sử dụng CDN để host các tệp font có thể giúp người truy cập của bạn tải font từ máy chủ trung gian gần nhất.
Trường hợp sử dụng font từ bên thứ ba như Google Font:
Đầu tiên bạn sử dụng thuộc tính preconnect
để thiết lập kết nối đến fonts.gstatic.com, sau đó dùng preload
để ưu tiên tải trước tập tin.
<link rel="preconnect"
href="https://fonts.gstatic.com"
crossorigin />
<link rel="preload"
as="style"
href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap" />
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap"
media="print" onload="this.media='all'" />
Mã nhúng và iFrames
Nguyên nhân
Mã nhúng cho phép bạn hiển thị nội dung web từ nơi khác trên trang của bạn – ví dụ: video YouTube, Google Maps, bài đăng trên Instagram, v.v. Tuy nhiên, có một vấn đề là hầu hết các tiện ích không bao gồm trước kích thước chính xác của nội dung được nhúng.
Giải pháp
Giải pháp để bạn có thể vừa giúp trình duyệt xác định trước kích thước của mã nhúng, vừa giữ được tỉ lệ khung hình khi resonsive là:
<div class="keep-aspect">
<iframe width="560" height="315" src="https://www.youtube.com/embed/jNQXAC9IVRw" frameborder="0" allowfullscreen></iframe>
</div>
.keep-aspect {
position: relative;
height: 0;
padding-top: 56.25%;
}
iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Ở đây chúng ta đặt giá trị paddding-top
= height / width * 100% = 315 / 560 * 100% = 56.25%, kết quả này cho ra chiều cao của mã nhúng, và nó responsive trên mọi thiết bị.
Dynamic contents (Nội dung động)
Nguyên nhân
Có thể bạn đã gặp phải sự thay đổi bố cục do giao diện người dùng, khi các phần tử bất ngờ hiện lên ở đầu hoặc cuối khung hình trên trang web.
Nội dung động có khá nhiều loại, ví dụ như: — related contents (nội dung liên quan), newsletter signup forms (biểu mẫu đăng kí), hoặc sticky notification bars (các thanh thông báo)
Cách đơn giản nhất là chèn nội dung động bên dưới nội dung hiện có. Trừ trường hợp khi bạn phải hiển thị một nội dung động ở trên để phản hồi lại tương tác của người dùng.
Giải pháp
Nếu bắt buộc phải chèn nội dung động bên trên nội dung hiện có, bạn cần xác định trước khoảng không gian cho nội dung động đó (ví dụ như tạo placeholder hoặc skeleton UI), với mục đích bảo toàn bố cục trang web khi tải.
Tốc độ trang web
Bất kỳ sự thay đổi nào về bố cục để phản hồi với tương tác của người dùng đều là những sự thay đổi tốt. Tuy nhiên, trang web của bạn phải tải bất cứ thứ gì nó cần tải trong vòng 0,5 giây (500 mili giây) kể từ lần tương tác cuối cùng của người dùng để không bị tính vào điểm CLS . Vì vậy, về cơ bản, việc tối ưu hóa trang web của bạn để tăng các chỉ số về speed (tốc độ) và responsiveness (sự phản hồi) thực sự quan trọng đối với điểm CLS của trang web.
Animations (Hiệu ứng chuyển động)
Nguyên nhân
Animations chắc chắn có thể nâng cao trải nghiệm người dùng chỉ khi bạn tích hợp vào trang web một cách chính xác. Nếu một hiệu ứng chuyển động gây ra sự thay đổi về kích thước như width và height của một phần tử, nó sẽ dẫn đến sự thay đổi vị trí, hậu quả dẫn đến vấn đề CLS.
Giải pháp
- Thay vì biến đổi thuộc tính
height
vàwidth
của một phần tử, hãy sử dụngtransform: scale()
. - Để dịch chuyển một phần tử, tránh thay đổi các thuộc tính top, right, bottom, left, và thay vào đó là
transform: translate()
. - Chắc chắn rằng các hiệu ứng chuyển động kéo dài dưới 500ms. Bạn nên sử dụng linear animation, có tốc độ không đổi, thay vì “ease”, tăng tốc độ tại thời điểm đầu và chậm lại ở cuối chuyển động và có thời gian thực thi lâu hơn.
- Để tìm hiểu thêm các thuộc tính CSS nào gây thay đổi bố cục trang web, bạn tham khảo thêm CSS Triggers và High-performance animations.
Kết luận
Việc tối ưu hóa điểm CLS là một quá trình dài và gồm nhiều quá trình. Mặc dù nó có thể không có tác động đáng kể đến xếp hạng công cụ tìm kiếm tại thời điểm hiện tại so với các chỉ số Core Web Vitals khác, nhưng vì Google ngày càng thu thập nhiều thêm dữ liệu trường liên quan đến điểm CLS, đây sẽ trở thành một số liệu quan trọng trong thời gian tới.
Ngoài ra, bằng cách loại bỏ hoặc giảm các thay đổi về bố cục, bạn sẽ cải thiện trải nghiệm người dùng trên trang web của mình, do đó có thể dẫn đến sự gia tăng chuyển đổi và tỷ lệ chuyển đổi (CTR). Bất kể bạn nhìn vào nó như thế nào, tối ưu hóa điểm CLS luôn đem lại những lợi ích đáng kể.