Tải từng phần hình ảnh ở cấp trình duyệt dành cho web

Hỗ trợ trình duyệt

  • Chrome: 77.
  • Edge: 79.
  • Firefox: 75.
  • Safari: 15.4.

Bạn có thể sử dụng thuộc tính loading để tải hình ảnh từng phần mà không cần viết mã tải từng phần tuỳ chỉnh hoặc sử dụng thư viện JavaScript riêng. Dưới đây là một bản minh hoạ về tính năng này:

Hình ảnh tải từng phần sẽ tải khi người dùng cuộn qua trang.

Trang này trình bày chi tiết cách triển khai tính năng tải lười trong trình duyệt.

Tại sao nên tải từng phần ở cấp trình duyệt?

Theo Lưu trữ HTTP, hình ảnh là loại thành phần được yêu cầu nhiều nhất đối với hầu hết các trang web và thường chiếm nhiều băng thông hơn bất kỳ tài nguyên nào khác. Ở phân vị thứ 90, các trang web gửi hơn 5 MB hình ảnh trên máy tính và thiết bị di động.

Trước đây, có hai cách để trì hoãn việc tải hình ảnh ngoài màn hình:

Cả hai tuỳ chọn này đều có thể cho phép nhà phát triển đưa hành vi tải lười vào, và nhiều nhà phát triển đã xây dựng thư viện bên thứ ba để cung cấp các tính năng trừu tượng dễ sử dụng hơn.

Tuy nhiên, với tính năng tải lười do trình duyệt hỗ trợ trực tiếp, bạn không cần thư viện bên ngoài. Tính năng tải từng phần ở cấp trình duyệt cũng đảm bảo rằng việc tải hình ảnh vẫn hoạt động ngay cả khi ứng dụng tắt JavaScript. Tuy nhiên, xin lưu ý rằng quá trình tải chỉ bị trì hoãn khi JavaScript được bật.

Thuộc tính loading

Chrome tải hình ảnh theo các mức độ ưu tiên khác nhau, tuỳ thuộc vào vị trí của hình ảnh đó so với khung nhìn của thiết bị. Hình ảnh bên dưới khung nhìn được tải với mức độ ưu tiên thấp hơn, nhưng vẫn được tìm nạp khi trang tải.

Bạn có thể sử dụng thuộc tính loading để trì hoãn hoàn toàn việc tải hình ảnh ngoài màn hình:

<img src="image.png" loading="lazy" alt="…" width="200" height="200">

Sau đây là các giá trị được hỗ trợ cho thuộc tính loading:

  • lazy: Hoãn tải tài nguyên cho đến khi tài nguyên đó đạt đến khoảng cách đã tính từ khung nhìn.
  • eager: Hành vi tải mặc định của trình duyệt, giống như việc không bao gồm thuộc tính này và có nghĩa là hình ảnh được tải bất kể vị trí của hình ảnh trên trang. Đây là giá trị mặc định, nhưng bạn nên đặt giá trị này một cách rõ ràng nếu công cụ của bạn tự động thêm loading="lazy" khi không có giá trị rõ ràng hoặc nếu trình tìm lỗi mã nguồn của bạn báo lỗi nếu giá trị này không được đặt rõ ràng.

Mối quan hệ giữa thuộc tính loading và mức độ ưu tiên tìm nạp

Giá trị eager là một lệnh để tải hình ảnh như bình thường, mà không làm chậm quá trình tải nếu hình ảnh nằm ngoài màn hình. Hình ảnh này không tải nhanh hơn một hình ảnh khác không có thuộc tính loading.

Nếu bạn muốn tăng mức độ ưu tiên tìm nạp của một hình ảnh quan trọng (ví dụ: hình ảnh LCP), hãy sử dụng Mức độ ưu tiên tìm nạp với fetchpriority="high".

Hình ảnh có loading="lazy"fetchpriority="high" vẫn bị trì hoãn khi nằm ngoài màn hình, sau đó được tìm nạp với mức độ ưu tiên cao khi gần nằm trong khung nhìn. Bạn không thực sự cần đến cách kết hợp này vì trình duyệt có thể sẽ tải hình ảnh đó ở mức độ ưu tiên cao.

Ngưỡng khoảng cách từ khung nhìn

Tất cả hình ảnh có thể xem ngay mà không cần cuộn tải bình thường. Hình ảnh nằm xa dưới khung nhìn thiết bị chỉ được tìm nạp khi người dùng cuộn gần hình ảnh đó.

Việc triển khai tính năng tải từng phần của Chromium cố gắng đảm bảo rằng hình ảnh ngoài màn hình được tải đủ sớm để hoàn tất quá trình tải trước khi người dùng cuộn đến hình ảnh đó bằng cách tìm nạp hình ảnh trước khi hình ảnh đó hiển thị trong khung nhìn.

Ngưỡng khoảng cách thay đổi tuỳ thuộc vào các yếu tố sau:

Bạn có thể tìm thấy các giá trị mặc định cho nhiều loại kết nối hiệu quả trong nguồn Chromium. Bạn có thể thử nghiệm với các ngưỡng này bằng cách kiểm soát tốc độ mạng trong DevTools.

Cải thiện ngưỡng tiết kiệm dữ liệu và khoảng cách từ khung nhìn

Vào tháng 7 năm 2020, Chrome đã cải thiện đáng kể để điều chỉnh các ngưỡng khoảng cách từ khung nhìn đến hình ảnh tải từng phần nhằm đáp ứng tốt hơn kỳ vọng của nhà phát triển.

Trên các kết nối nhanh (4G), chúng tôi đã giảm ngưỡng khoảng cách từ khung nhìn của Chrome từ 3000px xuống 1250px và trên các kết nối chậm hơn (3G trở xuống), thay đổi ngưỡng từ 4000px thành 2500px. Thay đổi này giúp đạt được hai mục đích:

  • <img loading=lazy> hoạt động gần giống với trải nghiệm mà các thư viện tải lười JavaScript cung cấp.
  • Các ngưỡng khoảng cách từ khung nhìn mới vẫn có nghĩa là hình ảnh có thể đã tải xong khi người dùng cuộn đến hình ảnh đó.

Tiếp theo, bạn có thể xem thông tin so sánh giữa ngưỡng khoảng cách từ khung nhìn cũ và mới cho một trong các bản minh hoạ của chúng tôi trên kết nối nhanh (4G):

Các ngưỡng mới và cải tiến cho tính năng tải từng phần hình ảnh, giảm ngưỡng khoảng cách từ khung nhìn cho các kết nối nhanh từ 3000 px xuống còn 1250 px.
So sánh ngưỡng cũ với ngưỡng mới dùng cho tính năng tải lười ở cấp trình duyệt.

và ngưỡng mới so với LazySizes (một thư viện tải lười JavaScript phổ biến):

Các ngưỡng khoảng cách từ khung nhìn mới trong Chrome tải 90 KB hình ảnh so với LazySizes tải 70 KB trong cùng điều kiện mạng.
So sánh các ngưỡng dùng để tải từng phần trong Chrome và LazySizes.

Cung cấp thuộc tính phương diện cho hình ảnh

Khi tải hình ảnh, trình duyệt không biết ngay kích thước của hình ảnh, trừ phi kích thước được chỉ định rõ ràng. Để trình duyệt dành đủ không gian trên trang cho hình ảnh và tránh thay đổi bố cục gây gián đoạn, bạn nên thêm thuộc tính widthheight vào tất cả thẻ <img>.

<img src="image.png" loading="lazy" alt="…" width="200" height="200">

Ngoài ra, bạn có thể chỉ định giá trị của các thuộc tính này trực tiếp trong kiểu cùng dòng:

<img src="image.png" loading="lazy" alt="…" style="height:200px; width:200px;">

Phương pháp hay nhất để đặt kích thước áp dụng cho thẻ <img> bất kể bạn có tải lười các thẻ đó hay không, nhưng tính năng tải lười có thể làm cho phương pháp này trở nên quan trọng hơn.

Tính năng tải từng phần trong Chromium được triển khai theo cách giúp hình ảnh có nhiều khả năng được tải ngay khi hiển thị, nhưng vẫn có khả năng hình ảnh sẽ không tải đúng thời điểm. Nếu điều đó xảy ra, việc không chỉ định widthheight trên hình ảnh sẽ làm tăng tác động của hình ảnh đó đối với Lỗi dịch chuyển bố cục tích luỹ. Nếu bạn không thể chỉ định kích thước hình ảnh, thì việc tải lười hình ảnh có thể tiết kiệm tài nguyên mạng với nguy cơ tăng số lần thay đổi bố cục.

Trong hầu hết các trường hợp, hình ảnh vẫn tải từng phần nếu bạn không chỉ định kích thước, nhưng bạn nên lưu ý một số trường hợp đặc biệt. Nếu không chỉ định widthheight, kích thước hình ảnh sẽ mặc định là 0×0 pixel. Nếu bạn có một thư viện hình ảnh, trình duyệt có thể quyết định rằng tất cả hình ảnh đều vừa với khung nhìn ở đầu, vì mỗi hình ảnh không chiếm không gian và không có hình ảnh nào bị đẩy ra khỏi màn hình. Trong trường hợp này, trình duyệt sẽ quyết định tải mọi thứ, khiến trang tải chậm hơn.

Để biết ví dụ về cách loading hoạt động với số lượng lớn hình ảnh, hãy tham khảo bản minh hoạ này.

Bạn cũng có thể tải lười hình ảnh mà bạn đã xác định bằng phần tử <picture>:

<picture>
  <source media="(min-width: 800px)" srcset="large.jpg 1x, larger.jpg 2x">
  <img src="photo.jpg" loading="lazy">
</picture>

Mặc dù trình duyệt quyết định hình ảnh nào sẽ tải từ bất kỳ phần tử <source> nào, nhưng bạn chỉ cần thêm loading vào phần tử dự phòng <img>.

Luôn tải trước hình ảnh hiển thị trong khung nhìn đầu tiên

Đối với hình ảnh hiển thị khi người dùng tải trang lần đầu, đặc biệt là đối với hình ảnh LCP, hãy sử dụng tính năng tải trước mặc định của trình duyệt để hình ảnh có thể hiển thị ngay lập tức. Để biết thêm thông tin, hãy xem phần Hiệu ứng của việc tải lười quá mức đối với hiệu suất.

Chỉ sử dụng loading=lazy cho hình ảnh nằm ngoài khung nhìn ban đầu. Trình duyệt không thể tải lười một hình ảnh cho đến khi biết vị trí của hình ảnh trên trang, điều này khiến hình ảnh tải chậm hơn.

<!-- visible in the viewport -->
<img src="product-1.jpg" alt="..." width="200" height="200">
<img src="product-2.jpg" alt="..." width="200" height="200">
<img src="product-3.jpg" alt="..." width="200" height="200">

<!-- offscreen images -->
<img src="product-4.jpg" loading="lazy" alt="..." width="200" height="200">
<img src="product-5.jpg" loading="lazy" alt="..." width="200" height="200">
<img src="product-6.jpg" loading="lazy" alt="..." width="200" height="200">

Xuống cấp nhẹ

Những trình duyệt không hỗ trợ thuộc tính loading sẽ bỏ qua thuộc tính này. Những người dùng này không nhận được lợi ích của tính năng tải lười, nhưng việc thêm tính năng này sẽ không gây ra tác động tiêu cực nào.

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

Một số câu hỏi thường gặp về tính năng tải lười ở cấp trình duyệt.

Tôi có thể tự động tải lười hình ảnh trong Chrome không?

Trước đây, Chromium tự động tải lười bất kỳ hình ảnh nào phù hợp với việc trì hoãn nếu Chế độ Lite được bật trên Chrome dành cho Android và thuộc tính loading không được cung cấp hoặc được đặt thành loading="auto". Tuy nhiên, chế độ Lite và loading="auto" không còn được dùng nữa và chúng tôi không có kế hoạch tự động tải lười hình ảnh trong Chrome.

Tôi có thể thay đổi khoảng cách gần nhất của hình ảnh với khung nhìn trước khi hình ảnh tải không?

Các giá trị này được mã hoá cứng và không thể thay đổi thông qua API. Tuy nhiên, các giá trị này có thể thay đổi trong tương lai khi các trình duyệt thử nghiệm với các khoảng cách và biến ngưỡng khác nhau.

Hình nền CSS có thể sử dụng thuộc tính loading không?

Không, bạn chỉ có thể sử dụng thuộc tính này với thẻ <img>.

Việc sử dụng loading="lazy" có thể ngăn tải hình ảnh khi hình ảnh không hiển thị nhưng nằm trong khoảng cách đã tính. Những hình ảnh này có thể nằm sau băng chuyền hoặc bị CSS ẩn đối với một số kích thước màn hình nhất định. Ví dụ: Chrome, Safari và Firefox không tải hình ảnh bằng cách sử dụng kiểu display: none;, trên phần tử hình ảnh hoặc trên phần tử mẹ. Tuy nhiên, các kỹ thuật ẩn hình ảnh khác, chẳng hạn như sử dụng kiểu opacity:0, vẫn khiến trình duyệt tải hình ảnh. Luôn kiểm tra kỹ lưỡng cách triển khai để đảm bảo cách triển khai đó hoạt động như dự kiến.

Chrome 121 đã thay đổi hành vi cho hình ảnh cuộn theo chiều ngang như băng chuyền. Các hành động này hiện sử dụng cùng ngưỡng với thao tác cuộn dọc. Điều này có nghĩa là đối với trường hợp sử dụng băng chuyền, hình ảnh sẽ được tải trước khi hiển thị trong khung nhìn. Điều này có nghĩa là người dùng ít nhận thấy quá trình tải hình ảnh hơn, nhưng chi phí là số lượt tải xuống sẽ tăng lên. Sử dụng bản minh hoạ Tải lười theo chiều ngang để so sánh hành vi trong Chrome với Safari và Firefox.

Nếu tôi đang sử dụng thư viện hoặc tập lệnh của bên thứ ba để tải hình ảnh từng phần thì sao?

Với tính năng tải lười được tích hợp đầy đủ vào các trình duyệt hiện đại, có thể bạn không cần thư viện hoặc tập lệnh của bên thứ ba để tải lười hình ảnh.

Một lý do để tiếp tục sử dụng thư viện của bên thứ ba cùng với loading="lazy" là để cung cấp polyfill cho các trình duyệt không hỗ trợ thuộc tính này hoặc để có nhiều quyền kiểm soát hơn đối với thời điểm kích hoạt tính năng tải lười.

Làm cách nào để xử lý những trình duyệt không hỗ trợ tính năng tải lười?

Tính năng tải lười hình ảnh ở cấp trình duyệt được hỗ trợ tốt trên tất cả các trình duyệt chính và được đề xuất cho hầu hết các trường hợp sử dụng để không cần thêm các phần phụ thuộc trên JavaScript.

Tuy nhiên, nếu cần hỗ trợ nhiều trình duyệt hơn hoặc muốn có nhiều quyền kiểm soát hơn đối với ngưỡng tải lười, thì bạn có thể sử dụng thư viện của bên thứ ba để tải lười hình ảnh trên trang web của mình.

Bạn có thể sử dụng thuộc tính loading để phát hiện xem trình duyệt có hỗ trợ tính năng này hay không:

if ('loading' in HTMLImageElement.prototype) {
  // supported in browser
} else {
  // fetch polyfill/third-party library
}

Ví dụ: lazysizes là một thư viện tải lười JavaScript phổ biến. Bạn chỉ có thể phát hiện tính năng hỗ trợ thuộc tính loading để tải lazysizes dưới dạng thư viện dự phòng khi loading không được hỗ trợ. Cách thức hoạt động như sau:

  • Thay thế <img src> bằng <img data-src> để tránh tải sớm trong các trình duyệt không được hỗ trợ. Nếu thuộc tính loading được hỗ trợ, hãy hoán đổi data-src cho src.
  • Nếu loading không được hỗ trợ, hãy tải một phương thức dự phòng từ lazysizes và khởi chạy phương thức đó, sử dụng lớp lazyload để cho biết hình ảnh nào sẽ tải từng phần:
<!-- Let's load this in-viewport image normally -->
<img src="hero.jpg" alt="…">

<!-- Let's lazy-load the rest of these images -->
<img data-src="unicorn.jpg" alt="…" loading="lazy" class="lazyload">
<img data-src="cats.jpg" alt="…" loading="lazy" class="lazyload">
<img data-src="dogs.jpg" alt="…" loading="lazy" class="lazyload">

<script>
  if ('loading' in HTMLImageElement.prototype) {
    const images = document.querySelectorAll('img[loading="lazy"]');
    images.forEach(img => {
      img.src = img.dataset.src;
    });
  } else {
    // Dynamically import the LazySizes library
    const script = document.createElement('script');
    script.src =
      'https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.1.2/lazysizes.min.js';
    document.body.appendChild(script);
  }
</script>

Sau đây là một bản minh hoạ về mẫu này. Hãy thử trong một trình duyệt cũ để xem phương thức dự phòng hoạt động như thế nào.

Tính năng tải từng phần cho iframe có được hỗ trợ trong trình duyệt không?

Hỗ trợ trình duyệt

  • Chrome: 77.
  • Edge: 79.
  • Firefox: 121.
  • Safari: 16.4.

<iframe loading=lazy> cũng đã được chuẩn hoá. Điều này cho phép bạn tải lười các iframe bằng thuộc tính loading. Để biết thêm thông tin, hãy xem bài viết Đã đến lúc tải lười các iframe ngoài màn hình!

Tính năng tải lười ở cấp trình duyệt ảnh hưởng như thế nào đến quảng cáo trên trang web?

Tất cả quảng cáo hiển thị cho người dùng dưới dạng hình ảnh hoặc iframe tải lười giống như mọi hình ảnh hoặc iframe khác.

Hình ảnh được xử lý như thế nào khi in trang web?

Tất cả hình ảnh và iframe sẽ tải ngay khi trang được in. Hãy xem vấn đề #875403 để biết thông tin chi tiết.

Lighthouse có nhận ra tính năng tải từng phần ở cấp trình duyệt không?

Lighthouse 6.0 trở lên có yếu tố cao hơn trong các phương pháp tải lười hình ảnh ngoài màn hình có thể sử dụng nhiều ngưỡng khác nhau, cho phép các phương pháp đó vượt qua quy trình kiểm tra Trì hoãn hình ảnh ngoài màn hình.

Tải từng phần hình ảnh để cải thiện hiệu suất

Tính năng hỗ trợ trình duyệt tải hình ảnh từng phần có thể giúp bạn cải thiện hiệu suất của trang một cách dễ dàng hơn đáng kể.

Bạn có nhận thấy hành vi bất thường nào khi bật tính năng này trong Chrome không? Báo cáo lỗi!