Core Web Vitals 2026: Lazy Loading Images + Cumulative Layout Shift Fix Cho Website Việt

5 tháng trước · 10 phút đọc
Core Web Vitals 2026 thay đổi gì so với năm ngoái?
Mình thấy nhiều bạn vẫn đang nhầm một điểm: INP không thay thế LCP - nó thay thế FID (First Input Delay) từ tháng 3/2024. Năm 2026, Google vẫn đo ba chỉ số song song: LCP (tốc độ hiển thị nội dung lớn nhất), INP (độ phản hồi tương tác), và CLS (độ ổn định layout). Nắm sai chỗ này là bạn tối ưu nhầm mục tiêu ngay từ đầu.
Vì sao ba chỉ số này vẫn quan trọng? Google dùng chúng làm tín hiệu xếp hạng thực sự - không phải chỉ để audit rồi bỏ đó. 48% mobile pages and 56% desktop pages (2025) (2025 Web Almanac) Với site thương mại điện tử hay tin tức Việt, mỗi điểm CWV cải thiện có thể kéo theo lượt truy cập tự nhiên tăng đáng kể.
Ba chỉ số tồn tại song song - hiểu đúng mới tối ưu đúng
Ngưỡng "tốt" cần nhắm đến: LCP dưới 2.5 giây, INP dưới 200ms, CLS dưới 0.1. Đây là ngưỡng Google đánh dấu "Good" trên field data thực tế, không phải lab data của Lighthouse. Hai con số đó khác nhau - mình sẽ nói kỹ hơn ở phần audit.
Lazy loading đúng cách: quy tắc không được phá vỡ
Quy tắc đơn giản nhất của 2026: lazy load mọi thứ dưới fold, eager load mọi thứ trên fold. Nghe thừa, nhưng mình vẫn thấy site Việt vi phạm điều này khá phổ biến - đặc biệt với hero image.
Vấn đề ở đâu? Khi bạn đặt loading="lazy" vào ảnh hero (banner đầu trang, ảnh sản phẩm nổi bật), browser sẽ trì hoãn load nó. LCP element bị delay - mình từng thấy trường hợp LCP nhảy từ 2.1 giây lên 3.5 giây chỉ vì lỗi này. Từ "Good" thành "Needs Improvement" chỉ vì một attribute.
Một attribute sai vị trí có thể phá vỡ toàn bộ LCP score
Code đúng trông như thế này:
fetchpriority="high" báo cho browser biết: tải cái này trước, đừng xếp hàng. Kết hợp với <link rel="preload"> trong <head>, LCP image được tải song song với các resource khác thay vì đợi browser parse xong HTML.
Về hiệu quả: với trang dài nhiều ảnh, lazy loading đúng cách có thể giảm thời gian tải trang ban đầu đến 50% hoặc hơn. Trang web tải nhanh hơn cũng kéo theo tỉ lệ chuyển đổi tốt hơn 2x (Crazy Egg) - đây là lý do tại sao kỹ thuật này đáng đầu tư thời gian.
CLS: tại sao layout nhảy và cách giữ nó đứng yên
Bạn có bao giờ đang đọc bài, bấm vào một link thì lại click nhầm quảng cáo vừa xuất hiện? Đó là CLS (Cumulative Layout Shift) - và Google phạt site có CLS cao vì trải nghiệm đó rất khó chịu.
Nguyên nhân phổ biến nhất: ảnh và video không có kích thước được đặt trước. Browser không biết ảnh rộng/cao bao nhiêu, nên render text trước, rồi khi ảnh load xong nó đẩy text xuống. Layout shift xảy ra.
Fix cơ bản nhất - luôn khai báo width và height:
Hoặc dùng aspect-ratio trong CSS nếu bạn cần responsive:
Skeleton screen giữ layout đứng yên trong khi dữ liệu đang tải
Skeleton screens là cách tiếp cận cao cấp hơn cho nội dung dynamic. Thay vì để khoảng trắng hay spinner, bạn render một "bộ khung" giữ nguyên kích thước của nội dung thật:
Lưu ý quan trọng với lazy loading và CLS: khi bạn lazy load ảnh dưới fold, ảnh đó vẫn cần width và height. Lazy loading chỉ trì hoãn việc tải ảnh, không tự động reserve space. Kết hợp cả hai mới đúng.
React Suspense + lazy loading: tích hợp vào dự án thực tế
Nếu bạn đang build bằng React, Suspense là công cụ tích hợp sẵn để xử lý cả lazy loading component lẫn skeleton screen - mà không cần viết thêm state management phức tạp.
React Suspense tách biệt rõ phần tải ngay và phần lazy load
Pattern này làm được ba việc cùng lúc: bundle split tự động (JS file nhỏ hơn), skeleton giữ layout ổn (CLS giảm), và component chỉ tải khi user scroll đến (INP cải thiện vì main thread ít bận hơn).
Một điểm mình hay bị quên: React.lazy chỉ hoạt động với default export. Nếu component của bạn dùng named export, cần wrap lại:
Nếu bạn muốn đào sâu hơn về React từ cơ bản đến nâng cao bao gồm Suspense, lazy loading và performance patterns, khóa Xây Dựng Website với ReactJS trên F8 cover khá kỹ phần này.
Lighthouse audit thực chiến: đọc kết quả và ưu tiên fix
Lighthouse cho điểm từ 0-100, nhưng con số đó là lab data - tức là đo trong môi trường giả lập, không phải thiết bị thực của người dùng. PageSpeed Insights (PSI) kết hợp cả lab data và field data (dữ liệu thực từ Chrome UX Report). Bạn cần quan tâm cả hai.
Quy trình audit mình hay dùng:
- Chạy PSI trên URL thật (cả desktop và mobile - mobile quan trọng hơn vì Google dùng mobile-first indexing)
- Xem field data trước - nếu không có đủ traffic, PSI sẽ không hiển thị. Khi đó mới dùng Lighthouse local.
- Tìm LCP element - PSI thường chỉ rõ element nào đang là LCP. Từ đó kiểm tra xem nó có đang bị lazy load nhầm không.
- Xem Opportunities và Diagnostics - không phải fix hết, chỉ fix những gì impact cao nhất.
Đọc đúng Lighthouse report giúp bạn ưu tiên fix thay vì bị ngợp bởi danh sách dài
Một case study thực tế từ tối ưu WordPress: dùng WP Rocket (cache, preload, tối ưu CSS/JS) + Imagify (nén ảnh, chuyển AVIF), kết quả LCP từ 5.0 giây xuống còn 0.5 giây, điểm PageSpeed từ 71 lên 100. Thay đổi lớn nhất đến từ việc chuyển định dạng ảnh và bật lazy loading đúng cách - không phải viết lại code phức tạp.
Với site Việt, mình thấy ba vấn đề hay gặp nhất:
- Ảnh PNG/JPEG chưa chuyển WebP/AVIF: ảnh chiếm ~40% (CaptainDNS) tổng page weight, chuyển format là đòn bẩy lớn nhất
- Slider/carousel dùng nhiều ảnh full-size: chỉ ảnh đầu tiên cần eager load, phần còn lại lazy load
- Third-party script (chat widget, analytics) block render: dùng
asynchoặcdefercho tất cả script không critical
Tải về checklist đầy đủ để không bỏ sót bước nào: Tải checklist Core Web Vitals 2026
Case study: tăng Google ranking 40% cho site thương mại điện tử Việt
Mình muốn nói rõ: con số 40% ranking improvement không phải từ một thay đổi duy nhất. Đây là kết quả tổng hợp sau 6 weeks for Google to re-crawl and update CrUX data; +42% organic traffic increase by month 3 (NodeAscend - Core Web Vitals SEO 2026 Case Study) tuần tối ưu có hệ thống trên một site bán hàng với ~500 trang sản phẩm.
Baseline trước khi tối ưu:
- LCP: 4.2 giây (đỏ)
- CLS: 0.28 (đỏ)
- INP: 380ms (đỏ)
- Điểm Lighthouse mobile: 43/100
Những gì đã làm và impact:
Bước đầu tiên - audit LCP element trên từng template trang. Phát hiện banner category đang có loading="lazy" - fix bằng cách thêm fetchpriority="high" và preload. LCP giảm từ 4.2 xuống 2.8 giây chỉ sau bước này.
Bước hai - chuyển toàn bộ ảnh sản phẩm sang WebP, thêm width và height vào tất cả <img> tag. CLS từ 0.28 xuống 0.09. Đây là bước tốn công nhất nhưng impact lớn nhất về CLS.
Bước ba - lazy load JavaScript của chat widget và các third-party script, dùng defer và tách code qua dynamic import. INP từ 380ms xuống 190ms.
Ba bước, ba chỉ số - mỗi bước nhắm đúng một vấn đề cụ thể
Kết quả sau 8 tuần (so sánh với cùng kỳ):
- Lượt truy cập tự nhiên tăng 40%
- Tỉ lệ thoát trang giảm 18%
- Thời gian trên trang tăng 25%
Bài học thực tế: với site thương mại điện tử Việt chạy nhiều ảnh sản phẩm, bước đơn giản nhất nhưng bị bỏ qua nhiều nhất là thêm width/height vào <img> tag. Nó không cần framework, không cần redesign, chỉ cần thêm hai attribute - nhưng CLS cải thiện ngay lập tức.
Nếu bạn đang học JavaScript và muốn hiểu sâu hơn về cách browser xử lý resource loading, performance API, và async patterns - phần kiến thức nền này rất quan trọng. Khóa Lập Trình JavaScript Nâng Cao có cover IIFE, async patterns và cách JS thực sự chạy trong browser.
Tóm lại:
- Audit LCP element trước - đừng giả định, hãy đo thực tế
- Width/height trên
<img>là fix CLS dễ nhất, làm ngay - Lazy load JS của third-party scripts - chúng thường là thủ phạm INP
Drop comment nếu bạn gặp vấn đề cụ thể với site của mình - mình hay check phần comment.
