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ó width và height (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áoloading. - 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 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 JS | Không | Có (thêm byte tải) |
| Cú pháp | 1 thuộc tính HTML | data-src + init script |
| Rủi ro ảnh trống khi JS lỗi | Không | Có |
| Ả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
- Xác định ảnh LCP của trang (thường là hero) — không lazy load nó.
- Ảnh LCP để
eager+fetchpriority="high"(đúng một ảnh/trang). - Mọi ảnh dưới màn hình đầu:
loading="lazy". - Mọi ảnh đều có
widthvàheightđể chống giật bố cục. - 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.

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> và <iframe>. Ảnh nền CSS cần IntersectionObserver để hoãn tải.
