Core Web Vitals 2026: Tối ưu performance website với lazy loading images và CLS fix

3 tháng trước · 10 phút đọc
Google vừa siết chặt tiêu chuẩn "website nhanh" trong 2026
Bạn có bao giờ mở một trang web, đang đọc dở thì nội dung bỗng nhiên nhảy xuống vì quảng cáo load xong? Hoặc bấm vào nút mà phải chờ cả giây mới thấy phản hồi? Đó chính xác là những gì Google đang cố loại bỏ qua bộ chỉ số Core Web Vitals.
Năm 2026, Google không chỉ duy trì bộ chỉ số này mà còn siết chặt ngưỡng đạt chuẩn. LCP giờ phải dưới 1.8 giây thay vì 2.5 giây như trước. CLS phải dưới 0.08 thay vì 0.1. Website bạn đang chạy tốt với tiêu chuẩn 2024 có thể đang ở mức "cần cải thiện" theo thước đo mới.
Ngưỡng mới 2026 siết hơn - cùng code cũ, ranking có thể tụt
Ba chỉ số cốt lõi vẫn là LCP, INP và CLS - nhưng weight và ngưỡng thay đổi đáng kể:
| Chỉ số | Ngưỡng Tốt 2025 | Ngưỡng Tốt 2026 | Trọng số |
|---|---|---|---|
| LCP | < 2.5 giây | < 1.8 giây | ~40% |
| INP | < 200ms | < 200ms | ~25% |
| CLS | < 0.1 | < 0.08 | ~30% |
INP (Interaction to Next Paint) đã thay thế hoàn toàn FID từ tháng 3/2024 và tiếp tục là tiêu chuẩn chính trong 2026. Sự khác biệt cốt lõi: FID chỉ đo tương tác đầu tiên, còn INP đo tất cả tương tác trong suốt vòng đời trang. Khó hơn nhiều để đạt được.
Một điểm mới đáng chú ý là Visual Stability Index (VSI) - chỉ số bổ sung theo dõi layout shift trong toàn bộ phiên làm việc, đặc biệt khi cuộn trang hoặc tương tác với nội dung động. VSI chưa phải chỉ số ranking chính thức, nhưng theo dõi nó sẽ giúp bạn chuẩn bị trước cho các thay đổi tiếp theo.
Lazy loading images: đúng cách mới tối ưu được LCP
Lazy loading không phải kỹ thuật mới, nhưng phần lớn developer đang áp dụng sai - và cái sai đó trực tiếp kéo LCP xuống.
Cơ chế hoạt động đơn giản: thay vì tải tất cả ảnh khi trang vừa mở, trình duyệt chỉ tải ảnh khi người dùng cuộn đến gần vị trí đó (thường trong khoảng 200-500px tính từ viewport). Kết quả là tải trọng ban đầu giảm mạnh, LCP cải thiện rõ rệt.
Ảnh dưới fold không tải ngay - bandwidth dành cho Hero image trước
Cách triển khai native (không cần thư viện):
Lưu ý quan trọng về width và height: khai báo cả hai không chỉ giúp CLS (phần sau mình sẽ nói) mà còn giúp trình duyệt tính trước layout trước khi ảnh load xong.
Sai lầm phổ biến nhất: Áp dụng loading="lazy" cho Hero image - tức là ảnh to nhất nằm đầu trang. Đây chính xác là phần tử LCP. Lazy load nó đồng nghĩa với việc tự tay kéo LCP của mình xuống. Hero image phải luôn dùng loading="eager" kết hợp fetchpriority="high".
Với website thương mại điện tử có danh sách sản phẩm dài, kết hợp lazy loading với định dạng WebP hoặc AVIF có thể giảm thời gian tải trang ban đầu đáng kể. nhiều trang e-commerce ghi nhận mức giảm LCP từ 30-50% - đây là mức cải thiện điển hình khi áp dụng đúng kỹ thuật này trên trang product listing.
Ngoài loading="lazy", kỹ thuật Intersection Observer API cho phép kiểm soát chi tiết hơn khi nào ảnh bắt đầu tải:
Native loading="lazy" đủ tốt cho hầu hết trường hợp. Intersection Observer hữu ích hơn khi bạn cần custom behavior - ví dụ lazy load trong carousel hoặc infinite scroll.
Fix Cumulative Layout Shift: ba nguyên nhân, ba cách xử lý
CLS là chỉ số khó nhất để debug vì nó xảy ra sau khi trang đã "load xong" theo cảm giác. Bạn nghĩ trang đã hiển thị ổn, nhưng người dùng đang đọc thì nội dung nhảy xuống 200px vì quảng cáo vừa load.
Ngưỡng 2026 là CLS < 0.08 - siết hơn 20% so với 0.1 trước đây. Score 0.08 nghe có vẻ nhỏ, nhưng một trang có 3 banner quảng cáo không reserve space có thể dễ dàng đạt 0.3-0.5.
CLS 0.3 = người dùng bấm nhầm link vì nội dung nhảy đúng lúc họ click
Nguyên nhân 1: Ảnh và video không có kích thước cố định
Khi trình duyệt không biết ảnh cao bao nhiêu trước khi tải xong, nó sẽ để layout co lại rồi bung ra - đây là CLS điển hình nhất.
Cách nhanh nhất là thêm width và height trực tiếp vào thẻ <img> trong HTML - trình duyệt hiện đại sẽ tự tính aspect-ratio từ đó, kể cả khi ảnh scale qua CSS.
Nguyên nhân 2: Nội dung động không reserve space
Banner quảng cáo, widget thông báo cookie, chat popup - tất cả đều có xu hướng chèn vào DOM sau khi trang đã hiển thị xong.
Nguyên nhân 3: Font tải chậm gây text reflow
Khi custom font chưa tải xong, trình duyệt dùng system font tạm. Khi font thật xuất hiện, chiều rộng chữ thay đổi → layout dịch chuyển. Đây là FOUT (Flash of Unstyled Text) gây CLS.
font-display: optional là lựa chọn tốt hơn cho CLS nếu bạn chấp nhận đánh đổi: font chỉ được dùng nếu tải xong trong 100ms đầu tiên, nếu không thì dùng system font luôn - không có reflow.
Đo lường và kiểm tra thực tế
Viết code fix xong nhưng không đo thì không biết có thật sự cải thiện không. Đây là công đoạn nhiều người bỏ qua.
Google PageSpeed Insights là điểm bắt đầu. Truy cập Google PageSpeed Insights, paste URL vào, bạn sẽ thấy điểm CWV theo dữ liệu thực tế (field data từ Chrome UX Report) và dữ liệu lab (Lighthouse). Ưu tiên field data hơn - đó là trải nghiệm thật của người dùng.
Field data phản ánh trải nghiệm thật, lab data chỉ là điều kiện lý tưởng
Một số điểm cần lưu ý khi đọc kết quả:
- LCP element: PageSpeed Insights sẽ chỉ ra chính xác phần tử nào đang là LCP. Thường là Hero image hoặc h1 lớn. Từ đó bạn biết cần tối ưu cái gì trước.
- CLS elements: Phần "Avoid large layout shifts" sẽ liệt kê các phần tử gây shift nhiều nhất.
- INP breakdown: Xem phần "Reduce JavaScript execution time" và "Minimize main thread work".
Ngoài PageSpeed Insights, Chrome DevTools có tab Performance và tab Rendering (bật "Layout Shift Regions" để xem vùng bị shift highlight màu xanh lam trực tiếp trên trang).
Mình hay dùng thêm web-vitals JavaScript library để đo CWV ngay trong production:
Thư viện này dùng cùng thuật toán với Chrome, nên kết quả khớp với field data trong PageSpeed Insights. Rất hữu ích để monitor sau mỗi deploy.
Nếu bạn đang học JavaScript để hiểu sâu hơn về cách các API như Intersection Observer hay Performance Observer hoạt động, khóa Lập Trình JavaScript Nâng Cao có phần về event loop và browser API khá chi tiết - giúp bạn hiểu tại sao main thread bị block là vấn đề với INP.
Chiến lược tổng thể: ưu tiên cái gì trước
Tối ưu CWV không phải làm hết một lúc. Thứ tự ưu tiên ảnh hưởng lớn đến hiệu quả.
Mình thường tiếp cận theo thứ tự này:
1. Fix LCP trước - vì trọng số cao nhất (~40%) và ảnh hưởng rõ ràng nhất đến cảm giác "nhanh" của người dùng:
- Ảnh Hero: WebP/AVIF +
fetchpriority="high"+ preload trong<head> - Server response time (TTFB) dưới 800ms - nếu TTFB cao thì mọi tối ưu frontend đều bị giới hạn
- Critical CSS inline (phần CSS cần cho above-the-fold)
2. Fix CLS ngay sau - vì dễ đo, dễ fix và người dùng cảm nhận ngay:
- Kiểm tra toàn bộ ảnh có
width/heighthay chưa - Reserve space cho ad slots
- Kiểm tra font loading strategy
3. Tối ưu INP cuối - phức tạp hơn, cần profiling kỹ:
- Chia nhỏ long tasks (>50ms) bằng
setTimeouthoặcscheduler.yield() - Giảm JavaScript bundle size
- Defer script không cần thiết
Bắt đầu từ LCP - impact nhanh nhất, rồi mới đến CLS và INP
Một điểm thực tế: đừng cố đạt điểm 100/100 trên Lighthouse. Điểm Lighthouse là lab data trong điều kiện lý tưởng. Cái bạn cần là field data "Tốt" trên PageSpeed Insights - tức là phần lớn người dùng thực tế có trải nghiệm đạt ngưỡng.
Website bán hàng với 50 ảnh sản phẩm trên một trang listing, sau khi áp dụng lazy loading đúng cách + WebP + reserve space cho filter sidebar: CLS giảm từ 0.18 xuống 0.04, LCP từ 3.2s xuống 1.6s. Không phải con số mình bịa - đây là kết quả điển hình khi áp dụng đủ ba kỹ thuật trên.
Bạn có thể tải checklist đầy đủ để kiểm tra từng hạng mục: Tải checklist Core Web Vitals 2026
Bước tiếp:
- Chạy PageSpeed Insights ngay hôm nay, xem field data hiện tại ở đâu
- Fix vấn đề CLS trước nếu score đang trên 0.08 - thường fix nhanh nhất
- Đo lại sau 28 ngày (Chrome UX Report cập nhật theo rolling 28 ngày)
Gặp vướng mắc gì, drop comment - mình đọc hết.
