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

  • 77
  • 79
  • 75
  • 15,4

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

Hình ảnh được 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 từng phần trong trình duyệt.

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

Theo HTTP Archive, hình ảnh là loại thành phần được yêu cầu nhiều nhất cho hầu hết các trang web và chúng 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ó 2 cách để trì hoãn việc tải hình ảnh ngoài màn hình:

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

Tuy nhiên, với tính năng tải từng phần được 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 quá trình tải hình ảnh vẫn hoạt động ngay cả khi ứng dụng tắt JavaScript. Tuy nhiên, lưu ý rằng việc tải chỉ bị trì hoãn khi JavaScript được bật.

Thuộc tính loading

Chrome tải hình ảnh ở những mức độ ưu tiên khác nhau tuỳ thuộc vào vị trí đặt 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 bằng mức độ ưu tiên thấp hơn nhưng chúng vẫn được tìm nạp khi trang tải.

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

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

Sau đây là những 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 đó đến khoảng cách tính toán từ khung nhìn.
  • eager: Hành vi tải mặc định của trình duyệt, giống với bao gồm thuộc tính và có nghĩa là hình ảnh sẽ được tải bất kể hình ảnh đó nằm ở đâu trên trang. Đây là giá trị mặc định, nhưng bạn nên đặt 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 công cụ tìm lỗi mã nguồn của bạn phàn nàn nếu 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 trì hoãn sẽ tải thêm nếu hình ảnh nằm ngoài màn hình. Không tải được hình ảnh nhanh hơn so với 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 cho một hình ảnh quan trọng (ví dụ: hình ảnh LCP), 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ễ khi nó 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 như nằm trong khung nhìn. Sự kết hợp này không thực sự cần thiết vì trình duyệt sẽ vẫn có thể tải hình ảnh đó với 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 được ngay lập tức mà không cần cuộn trang sẽ tải như bình thường. Hình ảnh phía dưới khung nhìn của thiết bị chỉ được tìm nạp khi người dùng cuộn gần chúng.

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

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

Bạn có thể tìm thấy giá trị mặc định cho các loại kết nối hiệu quả khác nhau trong nguồn Chromium. Bạn có thể thử nghiệm với các ngưỡng khác nhau này bằng cách điều tiết mạng trong Công cụ cho nhà phát triển.

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

Vào tháng 7 năm 2020, Chrome đã thực hiện các điểm cải tiến quan trọng để điều chỉnh ngưỡng khoảng cách từ khung nhìn của 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 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 này từ 4000px thành 2500px. Thay đổi này đạt được hai mục đích:

  • <img loading=lazy> có hành vi gần hơn với trải nghiệm do các thư viện tải từng phần JavaScript cung cấp.
  • Các ngưỡng mới về khoảng cách từ khung nhìn vẫn có nghĩa là hình ảnh có thể sẽ được tải vào thời điểm người dùng cuộn đến.

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

Ngưỡng cũ so với ngưỡng mới:

Các ngưỡng mới và được 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ừ 3000px xuống còn 1250px.
So sánh các ngưỡng cũ so với ngưỡng mới dùng cho tính năng tải từng phần gốc.

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

Các ngưỡng mới về khoảng cách từ khung nhìn trong Chrome khi tải hình ảnh là 90KB so với khi tải LazySizes trong 70KB 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 các thuộc tính kích thước hình ảnh

Mặc dù trình duyệt tải hình ảnh, trình duyệt không biết ngay trừ khi chúng được chỉ định rõ ràng. Để cho phép trình duyệt đặt trước đủ 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 các thuộc tính widthheight vào tất cả cá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 chúng trực tiếp theo 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 về việc đặt phương diện sẽ áp dụng cho thẻ <img> bất kể cho dù bạn đang tải từng phần, nhưng tải từng phần có thể khiến quá trình tải 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 tăng khả năng được tải ngay khi chúng xuất hiện, nhưng vẫn có khả năng nhưng chúng sẽ không tải vào đúng thời điểm. Trong trường hợp đó, việc không chỉ định widthheight trên hình ảnh của bạn làm tăng tác động của chúng đến Điểm số tổng hợp về mức thay đổi bố cục. Nếu bạn không thể chỉ định hình ảnh của mình các phương diện, tải từng phần có thể tiết kiệm mạng có nguy cơ chịu việc thay đổi bố cục gia tăng này.

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

Để xem ví dụ về cách loading hoạt động với một 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 từng phần 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 sẽ quyết định hình ảnh nào cần tải từ bất kỳ <source> nào bạn chỉ cần thêm loading vào phần tử <img> dự phòng.

Hình ảnh luôn tải nhanh hiển thị trong khung nhìn đầu tiên

Đối với những hình ảnh xuất hiện khi người dùng tải trang lần đầu tiên và đặc biệt đối với hình ảnh LCP, hãy dùng chế độ tải nhanh theo mặc định của trình duyệt để các hình ảnh này có thể xuất hiện ngay lập tức. Để biết thêm thông tin, hãy xem bài viết Ảnh hưởng về hiệu suất khi tải từng phần quá nhiều.

Chỉ sử dụng loading=lazy cho hình ảnh bên ngoài khung nhìn ban đầu. Trình duyệt không thể tải từng phần một hình ảnh cho đến khi biết được vị trí của hình ảnh trên trang, khiến chúng 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. Họ sẽ không nhận được lợi ích của tính năng tải từng phần, nhưng việc thêm tính năng này sẽ không có tác động tiêu cực.

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

Tôi có thể tự động tải từng phần hình ảnh trong Chrome không?

Trước đây, Chromium tự động tải từng phần bất kỳ hình ảnh nào phù hợp bị 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 bật được cung cấp hoặc đặt thành loading="auto". Tuy nhiên, Chế độ thu gọn và loading="auto" đã ngừng hoạt động và hiện chưa có kế hoạch cung cấp tính năng tự động tải từng phần hình ảnh trong Chrome.

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

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

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 với thẻ <img>.

Việc sử dụng loading="lazy" có thể ngăn việc tải hình ảnh khi bạn không tải hình ảnh 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 một băng chuyền hoặc bị CSS ẩn khỏi một số màn hình nhất định kích thước. Ví dụ: Chrome, Safari và Firefox không tải hình ảnh bằng Định 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 opacity:0 định kiểu, nhưng vẫn khiến trình duyệt tải hình ảnh. Luôn kiểm tra kỹ lưỡng để đảm bảo quảng cáo hoạt động như dự kiến.

Chrome 121 đã thay đổi cách hoạt động của hình ảnh cuộn ngang như băng chuyền. Các tuỳ chọn này hiện sử dụng cùng một ngưỡng như 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 có khả năng nhận thấy việc tải hình ảnh, nhưng sẽ làm tăng lượt tải xuống. Sử dụng bản minh hoạ Tải từng phần theo chiều ngang để so sánh hành vi trên Chrome với Safari và Firefox.

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

Với sự hỗ trợ đầy đủ của tính năng tải từng phần được tích hợp vào các trình duyệt hiện đại, có lẽ bạn sẽ không cần cần một thư viện hoặc tập lệnh của bên thứ ba để tải từng phần 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 một polyfill cho những 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 từng phần.

Làm thế nào để xử lý các trình duyệt không hỗ trợ tính năng tải từng phần?

Tạo một tệp polyfill hoặc sử dụng thư viện của bên thứ ba để tải từng phần hình ảnh trên trang web của bạn. Bạn có thể sử dụng thuộc tính loading để xác định xem trình duyệt có hỗ trợ tính năng:

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

Ví dụ: lazysizes là Thư viện JavaScript tải từng phần. Bạn có thể phát hiện loading có hỗ trợ hay không để tải lazysizes dưới dạng thư viện dự phòng chỉ khi loading không được hỗ trợ. Phương thức này hoạt động như sau:

  • Thay thế <img src> bằng <img data-src> để tránh tải nhanh 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 với giá src.
  • Nếu loading không được hỗ trợ, hãy tải một bản dự phòng từ lazysize và bắt đầu phương thức đó bằng cách sử dụng lớp lazyload để cho biết cần tải từng phần hình ảnh nào:
<!-- 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à bản minh hoạ về mẫu này. Hãy thử tính năng này trong trình duyệt cũ để xem tính năng dự phòng trong thực tế.

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

  • 77
  • 79
  • 121
  • 16,4

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

Tính năng tải từng phần ở 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 từng phần giống như bất kỳ quảng cáo nào khác hình ảnh hoặc iframe.

Google xử lý hình ảnh như thế nào khi in một trang web?

Tất cả hình ảnh và iframe đều tải ngay lập tức khi trang được in. Xem vấn đề #875403 để biết 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 và yếu tố cao hơn phương pháp tải từng phần hình ảnh ngoài màn hình có thể sử dụng các ngưỡng khác nhau, cho phép họ truyền Kiểm tra Hoãn phát 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

Trình duyệt hỗ trợ tính năng tải từng phần hình ảnh có thể giúp bạn thực hiện việc này dễ dàng hơn rất nhiều để cải thiện hiệu suất cho các trang của bạn hiệu suất.

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