Bỏ qua tới nội dung
Performance· ·9 phút đọc

Lazy load ảnh đúng cách (và bẫy ảnh hero làm chậm LCP)

Nguyễn Quốc An
Lazy load ảnh đúng cách (và bẫy ảnh hero làm chậm LCP)
Cỡ chữ

Trước đây, hoãn tải ảnh đòi hỏi một thư viện JavaScript theo dõi vị trí cuộn rồi mới đổ ảnh vào. Năm 2026, mọi trình duyệt phổ biến đã hỗ trợ sẵn cơ chế này ở mức gốc, nên phần lớn website chỉ cần một thuộc tính HTML là đủ. Điều quan trọng hơn cú pháp là biết ảnh nào nên hoãn và ảnh nào tuyệt đối không được hoãn — vì làm sai ở đúng tấm ảnh lớn nhất sẽ khiến trang chậm đi thay vì nhanh lên.

Vì sao hoãn tải ảnh lại tăng tốc trang

Một trang tin hay trang bán hàng thường có hàng chục ảnh, nhưng khi vừa mở, người dùng chỉ nhìn thấy phần trên cùng (above the fold — vùng hiện ra trước khi cuộn). Nếu trình duyệt tải hết mọi ảnh ngay từ đầu, băng thông và luồng ưu tiên bị chia cho cả những ảnh nằm tận cuối trang mà người dùng có thể không bao giờ cuộn tới.

Hoãn tải giải quyết đúng điểm này: các ảnh dưới màn hình chỉ được tải khi người dùng cuộn gần tới. Nhờ đó dữ liệu cần thiết cho màn hình đầu được ưu tiên, byte tải về ban đầu giảm, và những phần tử quan trọng hiện ra sớm hơn. Đây là một đòn bẩy rẻ tiền cho tối ưu Core Web Vitals, đặc biệt với trang nhiều hình.

Cách chuẩn 2026: loading=”lazy” native

Cách được khuyến nghị hiện nay là dùng thuộc tính loading gốc của trình duyệt. Một dòng HTML, không cần thư viện:

<img
  src="/anh/san-pham-cuon-tay.webp"
  alt="Cuốn tay nem nướng Nha Trang"
  width="800" height="600"
  loading="lazy">

Thuộc tính này nhận hai giá trị: lazy (hoãn cho tới khi gần viewport) và eager (tải ngay — đây cũng là mặc định khi không khai báo). Trình duyệt tự lo phần theo dõi cuộn. Theo tài liệu của web.dev, ngưỡng kích hoạt nằm dưới viewport khoảng 1.250px trên mạng 4G và 2.500px trên 3G hoặc chậm hơn — nghĩa là ảnh được nạp trước một quãng vừa đủ để khi người dùng cuộn tới thì ảnh đã sẵn sàng, không bị nháy trắng.

Về hỗ trợ trình duyệt: Chrome 77+, Edge 79+, Firefox 75+ và Safari 15.4+ đều chạy được. Con số này bao phủ hơn 95% người dùng thực tế, nên với đa số dự án, native là đủ.

Luôn khai báo width và height

Một lỗi hay đi kèm hoãn tải là quên đặt kích thước ảnh. Khi ảnh chưa tải, nếu không có widthheight (hoặc aspect-ratio trong CSS), trình duyệt không biết chừa bao nhiêu chỗ, dẫn tới giật bố cục khi ảnh nhảy vào. Đây là nguồn gốc phổ biến của điểm CLS xấu (Cumulative Layout Shift — tổng dịch chuyển bố cục). Hãy luôn ghi kích thước thật của ảnh; phần co giãn theo màn hình để CSS lo. Chi tiết kỹ thuật chống giật ở bài dùng aspect-ratio chống layout shift.

Bẫy lớn nhất: đừng lazy load ảnh LCP / ảnh hero

Đây là phần nhiều người làm ngược. Lời khuyên cũ “lazy load tất cả ảnh cho nhẹ” đã hết đúng. Ảnh hero — tấm lớn nhất ở đầu trang — thường chính là phần tử quyết định LCP (Largest Contentful Paint — thời điểm phần tử lớn nhất hiện ra). Nếu bạn gắn loading="lazy" cho nó, trình duyệt sẽ trì hoãn việc tải cho tới khi xác định nó vào viewport, thay vì tải ngay. Theo các phép đo của Google và web.dev, sai lầm này có thể cộng thêm khoảng 500ms vào LCP — đủ để đẩy một trang từ “Good” rớt xuống ngưỡng kém.

Quy tắc gọn để nhớ:

  • Trên màn hình đầu (ảnh hero, banner, ảnh sản phẩm chính): để tải ngay — loading="eager" hoặc đơn giản là không khai báo loading.
  • Dưới màn hình đầu (ảnh trong thân bài, gallery, footer): mới loading="lazy".

Với đúng tấm ảnh LCP, nên đi xa hơn một bước: thêm fetchpriority="high" để báo trình duyệt ưu tiên tải nó trước. Google công bố trường hợp chỉ riêng thuộc tính này đã kéo LCP từ 2,6s xuống 1,9s.

<!-- Ảnh hero: tải ngay, ưu tiên cao -->
<img
  src="/anh/hero-trang-chu.webp"
  alt="Bộ sưu tập đèn gốm thủ công"
  width="1200" height="675"
  fetchpriority="high">

Lưu ý ngược lại: chỉ dùng fetchpriority="high" cho đúng một ảnh mỗi trang. Nếu gắn cho mọi ảnh thì không còn gì để trình duyệt hạ ưu tiên, lệnh “ưu tiên” trở nên vô nghĩa. Cảnh báo về ảnh LCP được nói kỹ hơn ở bài tối ưu LCP và cách đo.

So sánh lazy load ảnh làm đúng và các bẫy làm chậm LCP
Lazy đúng chỗ thì nhanh; lazy nhầm ảnh hero/LCP thì phản tác dụng.

So với thư viện lazyload JavaScript cũ

Các thư viện như lazysizes hay những đoạn script dựa trên thuộc tính data-src ra đời khi trình duyệt chưa hỗ trợ native. Năm 2026, chúng phần lớn đã thừa và còn kéo theo chi phí: tải thêm JavaScript, chạy thêm logic, và nếu cấu hình sai có thể khiến ảnh trống cho tới khi script chạy xong.

Tiêu chíNative loading=”lazy”Thư viện JS cũ
Phụ thuộc JSKhôngCó (thêm byte tải)
Cú pháp1 thuộc tính HTMLdata-src + init script
Rủi ro ảnh trống khi JS lỗiKhông
Ảnh nền CSS (background-image)Không hỗ trợCó thể làm được

Chỉ nên dùng thư viện JS khi cần tính năng native chưa có: placeholder mờ (blur-up), hoãn tải ảnh nền CSS (background-image không nhận thuộc tính loading), hoặc hỗ trợ Safari đời rất cũ. Khi đó, cách gọn là dùng IntersectionObserver tự viết thay vì cả một thư viện nặng.

Checklist nhanh khi đặt lazy load

  1. Xác định ảnh LCP của trang (thường là hero) — không lazy load nó.
  2. Ảnh LCP để eager + fetchpriority="high" (đúng một ảnh/trang).
  3. Mọi ảnh dưới màn hình đầu: loading="lazy".
  4. Mọi ảnh đều có widthheight để chống giật bố cục.
  5. Kết hợp với ảnh đa kích thước qua thuộc tính srcset để mỗi thiết bị tải đúng cỡ — xem bài responsive image với srcset và sizes.

Web22 vận hành web22.dev trên LiteSpeed kèm Cloudflare và đo Core Web Vitals bằng Lighthouse thực tế; trong các đợt kiểm tra, đặt sai trạng thái lazy cho ảnh đầu trang là một trong những nguyên nhân âm thầm nhất kéo LCP đi xuống — nhìn bề ngoài trang vẫn “có hoãn tải” nên dễ tưởng đã tối ưu. Nếu cần rà toàn bộ ảnh và chỉ số tốc độ một cách bài bản, bạn có thể tham khảo dịch vụ tối ưu tốc độ website của Web22.

Checklist nhanh khi đặt lazy load ảnh để tăng tốc mà không hại LCP
Bốn điểm kiểm nhanh để lazy load tăng tốc mà không hại LCP.

Câu hỏi thường gặp

Có nên lazy load mọi ảnh không?

Không. Ảnh trên màn hình đầu, nhất là ảnh LCP, phải tải ngay. Chỉ hoãn tải những ảnh nằm dưới màn hình đầu tiên.

loading=”lazy” có làm vỡ SEO không?

Không, nếu dùng đúng. Googlebot xử lý được native lazy loading. Vấn đề chỉ phát sinh khi ảnh phụ thuộc JavaScript phức tạp mới hiện ra — native HTML thì an toàn.

Ảnh nền CSS có lazy load được bằng thuộc tính này không?

Không. Thuộc tính loading chỉ áp dụng cho thẻ <img><iframe>. Ảnh nền CSS cần IntersectionObserver để hoãn tải.

Cần làm web?

Dịch vụ liên quan
tới chủ đề bài này.

Tất cả dịch vụ
Đọc tiếp

Bài viết
cùng chủ đề.

Tất cả bài viết