Ленивая загрузка изображений

Изображения могут появляться на веб-странице благодаря тому, что они встроены в HTML как элементы <img> или как фоновые изображения CSS. В этом посте вы узнаете, как лениво загружать оба типа изображений.

Встроенные изображения

Наиболее распространенными вариантами отложенной загрузки являются изображения, используемые в элементах <img> . При использовании встроенных изображений у нас есть три варианта отложенной загрузки, которые можно использовать в сочетании для лучшей совместимости между браузерами:

Использование отложенной загрузки на уровне браузера

Chrome и Firefox поддерживают отложенную загрузку с атрибутом loading . Этот атрибут можно добавить к элементам <img> , а также к элементам <iframe> . Значение lazy сообщает браузеру немедленно загрузить изображение, если оно находится в области просмотра, и получать другие изображения, когда пользователь прокручивает страницу рядом с ними.

Подробную информацию о поддержке браузеров см. в поле loading таблицы совместимости браузеров MDN. Если браузер не поддерживает отложенную загрузку, атрибут будет игнорироваться, и изображения будут загружаться немедленно, как обычно.

Для большинства веб-сайтов добавление этого атрибута к встроенным изображениям повысит производительность и избавит пользователей от загрузки изображений, которые они, возможно, никогда не прокрутят. Если у вас большое количество изображений и вы хотите быть уверены, что пользователи браузеров без поддержки отложенной загрузки получат выгоду, вам необходимо объединить это с одним из методов, описанных ниже.

Чтобы узнать больше, ознакомьтесь с отложенной загрузкой на уровне браузера для Интернета .

Использование наблюдателя пересечений

Для отложенной загрузки элементов <img> мы используем JavaScript, чтобы проверить, находятся ли они в области просмотра. Если да, то их атрибуты src (а иногда srcset ) заполняются URL-адресами желаемого содержимого изображения.

Если вы раньше писали код отложенной загрузки, возможно, вы выполнили свою задачу, используя обработчики событий, такие как scroll или resize . Хотя этот подход является наиболее совместимым во всех браузерах, современные браузеры предлагают более производительный и эффективный способ проверки видимости элементов с помощью Intersection Observer API .

Intersection Observer проще использовать и читать, чем код, основанный на различных обработчиках событий, поскольку вам нужно всего лишь зарегистрировать наблюдателя для наблюдения за элементами, а не писать утомительный код определения видимости элементов. Осталось только решить, что делать, когда элемент виден. Давайте предположим, что это базовый шаблон разметки для ваших лениво загружаемых элементов <img> :

<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!">

Есть три важных части этой разметки, на которых вам следует сосредоточиться:

  1. Атрибут class , с помощью которого вы выберете элемент в JavaScript.
  2. Атрибут src , который ссылается на изображение-заполнитель, которое появится при первой загрузке страницы.
  3. Атрибуты data-src и data-srcset — это атрибуты-заполнители, содержащие URL-адрес изображения, которое вы загрузите, как только элемент окажется в области просмотра.

Теперь давайте посмотрим, как использовать Intersection Observer в JavaScript для отложенной загрузки изображений с использованием этого шаблона разметки:

document.addEventListener("DOMContentLoaded", function() {
  var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));

  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.srcset = lazyImage.dataset.srcset;
          lazyImage.classList.remove("lazy");
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  } else {
    // Possibly fall back to event handlers here
  }
});

В событии DOMContentLoaded документа этот сценарий запрашивает в DOM все элементы <img> с классом lazy . Если доступен Intersection Observer, создайте нового наблюдателя, который запускает обратный вызов, когда элементы img.lazy попадают в область просмотра.

Intersection Observer доступен во всех современных браузерах. Поэтому использование его в качестве полифила для loading="lazy" гарантирует, что отложенная загрузка будет доступна большинству посетителей.

Изображения в CSS

Хотя теги <img> являются наиболее распространенным способом использования изображений на веб-страницах, изображения также можно вызывать с помощью свойства CSS background-image (и других свойств). Отложенная загрузка на уровне браузера не применяется к фоновым изображениям CSS, поэтому вам необходимо рассмотреть другие методы, если у вас есть фоновые изображения для отложенной загрузки.

В отличие от элементов <img> , которые загружаются независимо от их видимости, поведение загрузки изображений в CSS осуществляется с большим количеством предположений. Когда построены объектные модели документа и CSS, а также дерево рендеринга , браузер проверяет, как CSS применяется к документу, прежде чем запрашивать внешние ресурсы. Если браузер определил, что правило CSS, включающее внешний ресурс, не применяется к документу в его текущей версии, браузер не запрашивает его.

Это спекулятивное поведение можно использовать для отсрочки загрузки изображений в CSS, используя JavaScript для определения того, когда элемент находится в области просмотра, и последующего применения к этому элементу класса, который применяет стиль, вызывающий фоновое изображение. Это приводит к тому, что изображение загружается в нужный момент, а не при начальной загрузке. Например, возьмем элемент, содержащий большое фоновое изображение героя:

<div class="lazy-background">
  <h1>Here's a hero heading to get your attention!</h1>
  <p>Here's hero copy to convince you to buy a thing!</p>
  <a href="/buy-a-thing">Buy a thing!</a>
</div>

Элемент div.lazy-background обычно содержит фоновое изображение героя, вызываемое некоторым CSS. Однако в этом примере отложенной загрузки вы можете изолировать свойство background-image элемента div.lazy-background с помощью visible класса, добавляемого к элементу, когда он находится в области просмотра:

.lazy-background {
  background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}

.lazy-background.visible {
  background-image: url("hero.jpg"); /* The final image */
}

Отсюда используйте JavaScript, чтобы проверить, находится ли элемент в области просмотра (с помощью Intersection Observer!), и в это время добавьте visible класс к элементу div.lazy-background , который загружает изображение:

document.addEventListener("DOMContentLoaded", function() {
  var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));

  if ("IntersectionObserver" in window) {
    let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add("visible");
          lazyBackgroundObserver.unobserve(entry.target);
        }
      });
    });

    lazyBackgrounds.forEach(function(lazyBackground) {
      lazyBackgroundObserver.observe(lazyBackground);
    });
  }
});

Влияние на наибольшую содержательную отрисовку (LCP)

Отложенная загрузка — это отличная оптимизация, которая снижает как общее использование данных, так и конфликты в сети во время запуска, откладывая загрузку изображений до того момента, когда они действительно необходимы. Это может сократить время запуска и сократить обработку в основном потоке за счет сокращения времени, необходимого для декодирования изображения.

Однако отложенная загрузка — это метод, который может негативно повлиять на самый большой LCP контента вашего веб-сайта, если вы слишком увлечены этим методом. Единственное, чего вам следует избегать, — это ленивая загрузка изображений, которые находятся в области просмотра во время запуска.

При использовании отложенных загрузчиков на основе JavaScript вам следует избегать отложенной загрузки изображений в области просмотра, поскольку эти решения часто используют атрибут data-src или data-srcset в качестве заполнителя для атрибутов src и srcset . Проблема здесь в том, что загрузка этих изображений будет задерживаться, поскольку сканер предварительной загрузки браузера не сможет найти их во время запуска .

Даже использование отложенной загрузки на уровне браузера для отложенной загрузки изображения в области просмотра может иметь неприятные последствия. Когда loading="lazy" применяется к изображению в области просмотра, это изображение будет задержано до тех пор, пока браузер не узнает наверняка, что оно находится в области просмотра , что может повлиять на LCP страницы.

Никогда не лениво загружайте изображения, которые видны в области просмотра во время запуска. Это шаблон, который негативно повлияет на LCP вашего сайта и, следовательно, на удобство использования. Если вам нужен образ при запуске, загружайте его при запуске как можно быстрее, не ленясь его загружать!

Ленивая загрузка библиотек

Вам следует использовать отложенную загрузку на уровне браузера, когда это возможно, но если вы окажетесь в ситуации, когда это невозможно (например, значительная группа пользователей все еще зависит от старых браузеров), для отложенной загрузки можно использовать следующие библиотеки: изображений:

  • lazysizes — это полнофункциональная библиотека отложенной загрузки, которая лениво загружает изображения и iframe. Используемый шаблон очень похож на примеры кода, показанные здесь, поскольку он автоматически привязывается к классу lazyload элементов <img> и требует указания URL-адресов изображений в атрибутах data-src и/или data-srcset , содержимом которые заменяются атрибутами src и/или srcset соответственно. Он использует Intersection Observer (который можно полифиллить) и может быть расширен с помощью ряда плагинов для выполнения таких задач, как отложенная загрузка видео. Узнайте больше об использовании lazysizes .
  • vanilla-lazyload — это легкий вариант для отложенной загрузки изображений, фоновых изображений, видео, iframe и скриптов. Он использует Intersection Observer, поддерживает адаптивные изображения и обеспечивает отложенную загрузку на уровне браузера.
  • lozad.js — еще один облегченный вариант, использующий только Intersection Observer. Таким образом, он очень производительен, но его необходимо заполнить полифилом, прежде чем вы сможете использовать его в старых браузерах.
  • Если вам нужна библиотека отложенной загрузки, специфичная для React, рассмотрите возможность реакции-lazyload . Хотя он не использует Intersection Observer, он предоставляет знакомый метод отложенной загрузки изображений для тех, кто привык разрабатывать приложения с помощью React.