Attribute loading="lazy" báo cho trình duyệt trì hoãn việc tải một image hoặc iframe cho tới khi nó sắp vào viewport — tiết kiệm băng thông và tăng tốc lần tải ban đầu, không cần JavaScript.
Attribute loading="lazy" báo cho trình duyệt trì hoãn việc tải một image hoặc iframe cho tới khi nó sắp vào viewport — tiết kiệm băng thông và tăng tốc lần tải ban đầu, không cần JavaScript.
lazy — chỉ tải khi việc cuộn đưa nó tới gần viewport.eager (mặc định) — tải ngay lập tức, bất kể vị trí.Trình duyệt dùng một biên độ (tải sớm hơn một chút trước khi element cuộn vào tầm nhìn) để hình ảnh thường đã sẵn sàng vào lúc người dùng nhìn thấy nó.
<img src="x.jpg" loading="lazy" width="800" height="600" />
Nếu không có kích thước (hoặc một aspect-ratio), hình ảnh được tải lazy không có không gian dành sẵn, nên khi nó tải trang sẽ nhảy — gây hại cho Cumulative Layout Shift (CLS). Luôn dành sẵn không gian.
<!-- ❌ ảnh hero/LCP nên tải eager — lazy làm trì hoãn nó -->
<img src="hero.jpg" loading="lazy" />
<!-- ✅ -->
<img src="hero.jpg" loading="eager" fetchpriority="high" />
Lazy-load ảnh Largest Contentful Paint thực ra gây hại cho hiệu năng — nó làm trì hoãn pixel quan trọng nhất. Chỉ lazy-load media nằm ngoài màn hình.
// cách thủ công cũ mà lazy-loading native đã thay thế
const io = new IntersectionObserver((entries) => {
entries.forEach((e) => { if (e.isIntersecting) e.target.src = e.target.dataset.src; });
});
loading="lazy" native đã loại bỏ nhu cầu này trong hầu hết trường hợp (dù IntersectionObserver vẫn hữu ích cho logic tùy chỉnh).
Lazy loading native cắt giảm byte và request ban đầu cho các trang dài với nhiều hình ảnh — một thắng lợi lớn trên mobile — một cách miễn phí.
Các sắc thái rất quan trọng: dành sẵn kích thước để bảo vệ CLS, và giữ ảnh above-the-fold/LCP ở chế độ eager (thậm chí fetchpriority="high") để nội dung quan trọng vẫn tải nhanh.