Lazy Load для изображений на сайте — полное руководство

Для каждого современного сайта и приложения изображения имеют важное значение. Будь то рекламные баннеры, изображения продуктов или логотипы, невозможно представить сайт без изображений. К сожалению, картинки имеют большой размер, что делает их крупнейшими файлами при загрузке страницы. Согласно последним данным HTTP Archive , средний размер страницы сайта на десктопном компьютере составляет 1511 КБ. Изображения составляют почти 650 КБ от этого размера, то есть примерно 45% от общего размера страницы. Поскольку мы не можем отказаться от использования изображений на сайте, нам нужно заставить страницы с ними загружаться очень быстро. В этом руководстве мы поговорим об отложенной загрузке изображений — lazy load, технике, которая помогает сократить время загрузки страницы и уменьшить ее размер, сохраняя при этом все изображения на странице.

Что дает Lazy Load?
Видео ниже демонстрирует работу отложенной загрузки изображений на странице. Обратите внимание, что при прокрутке страницы серый заполнитель заменяется реальным изображением.

Что такое Lazy Load — отложенная загрузка изображений?

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

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

Техника отложенной загрузки может применяться практически ко всем ресурсам на странице. Например, в одностраничном приложении, если файл JS пока не нужен, лучше не загружать его сразу. Если изображение не нужно заранее, можно загрузить его позже, когда оно действительно понадобится.

Зачем откладывать загрузку картинок?

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

Это дает два основных преимущества.

  • 1. Оптимизация производительности

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

  • 2. Экономия трафика

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

Загрузка каких изображений может быть отложена?

Основная идея отложенной загрузки довольно проста — отложите загрузку всего, что сейчас не нужно. Любое изображение, которое не видно пользователю, может быть загружено потом. Когда пользователь прокручивает страницу, заполнители появляются в области просмотра (видимая часть веб-страницы). И когда эти изображения становятся видимыми, запускается их загрузка .

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

Техника отложенной загрузки изображений

Изображения на странице могут быть загружены двумя способами — с помощью тега <img> или с помощью свойства background в CSS. Сначала мы рассмотрим более общий из двух тегов <img>, а затем перейдем к фоновым изображениям CSS.

Общая концепция отложенной загрузки изображений в тег <img>

Отложенная загрузка изображений может быть разбита на два этапа.

Первый шаг — предотвратить загрузку изображения. Для изображений, загруженных с использованием тега <img> , браузер использует атрибут тега src для запуска загрузки изображения. Неважно, будет ли это 1-е или 1000-е изображение в вашем HTML и как далеко оно от начала страницы. Как только браузер получил атрибут src, он начинает загрузку изображения.

Таким образом, чтобы загружать такие изображения отложенно, нужно поместить URL-адрес изображения в атрибут, отличный от src. Допустим, мы указываем URL-адрес изображения в атрибуте data-src тега изображения. Теперь, так как атрибут src пуст, браузер не запускает загрузку изображения.

<img data-src = "https://ik.imagekit.io/demo/default-image.jpg" />

Теперь, когда мы остановили предварительную загрузку, нам нужно сообщить браузеру, когда ему загружать изображение. Для этого мы проверяем, что как только изображение (т.е. его заполнитель) попадает в область просмотра, мы запускаем загрузку. Есть два способа проверки нахождение изображения в области просмотра. 

Запуск загрузки изображения с использованием событий Javascript

В этой технике мы навешиваем слушатели на события scrollresizeи orientationChange в браузере. Событие прокрутки является очевидным для проверки прокрутки страницы. События resize и directionChange одинаково важны для отложенной загрузки. Событие resize происходит при изменении размера окна браузера. Событие directionChange срабатывает, когда устройство поворачивается из альбомного в портретный режим или наоборот. В таких случаях количество изображений, которые становятся видимыми на экране, изменится. Таким образом, нам нужно будет запустить загрузку для этих изображений.

Когда происходит любое из этих событий, мы находим все изображения на странице, которые должны быть загружены отложенно и еще не загружены. Далее мы проверяем, какие из этих изображений сейчас находятся в окне просмотра. Это делается с использованием значения
top offset изображения, свойств scroll top и window height текущего документа. Если изображение вошло в область просмотра, мы берем URL из атрибута data-src и помещаем его в атрибут
src. Это вызовет загрузку изображения. Мы также удаляем класс lazy, который идентифицирует изображения, загрузка которых будет отложена. Как только все изображения загружены, мы удаляем слушателей событий.d

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

Вот пример такого подхода.

See the Pen Lazy loading images using event handlers — example code by ImageKit.io (@imagekit_io) on CodePen.

Как вы могли заметить, первые 3 изображения в этом примере загружаются сразу. URL присутствует непосредственно в srcатрибуте вместо data-src. Это важно для обеспечения качественного опыта взаимодействия. Поскольку эти изображения находятся вверху страницы, их следует сделать видимыми как можно скорее. То есть мы не должны ждать события или выполнения JS, чтобы их загрузить.

Использование Intersection Observer API для запуска загрузки изображений

Intersection Observer API — это относительно новый браузерный API. Он упрощает обнаружение попадания элемента в область просмотра и выполнение действия при этом событии. В предыдущем методе нам приходилось использовать события, помнить о производительности и вычислять, находится ли элемент в области просмотра или нет. API Intersection Observer делает это намного проще, помогает избежать математики и обеспечивает отличную производительность.

Ниже приведен пример использования API Intersection Observer для отложенной загрузки изображений. Мы вешаем наблюдателя на все изображения, загрузку которых нужно задержать. Как только API обнаруживает, что элемент вошел в область просмотра, используя
свойство isIntersecting, мы берем URL из атрибута data-src и перемещаем его в атрибут src для вызова загрузки изображения. По завершении этого, мы удаляем класс Lazy из изображения, а также удаляем наблюдателя из этого изображения.

See the Pen Lazy loading images using IntersectionObserver — example code by ImageKit.io (@imagekit_io) on CodePen.

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

Однако, как и все новое в вебе, поддержка Intersection Observer API доступна не во всех браузерах. Итак, нам нужно использовать прослушивание событий в браузерах, где API-интерфейс Intersection Observer не поддерживается.

Отложенная загрузка фоновых изображений в CSS

Фоновые изображения являются вторым наиболее распространенным способом загрузки изображений на страницу. Для тегов <img /> браузер имеет очень простой подход — если URL изображения доступен, он его загрузит.

С фоновыми изображениями CSS не все так просто. Чтобы загрузить фоновые изображения CSS, браузер должен построить дерево DOM (объектная модель документа), а также дерево CSSOM (объектная модель CSS), чтобы решить, применяется ли стиль CSS к узлу DOM в текущем документе. Если правило CSS, задающее фоновое изображение, не применяется к элементу в документе, браузер не загружает фоновое изображение. Если правило CSS применяется к элементу в текущем документе, браузер загружает изображение.

На первый взгляд это может показаться сложным, но это же поведение формирует основу для отложенной загрузки фоновых изображений. Проще говоря, мы заставляем браузер не применять CSS-свойство background-image к элементу, пока этот элемент не попадет в область просмотра.

Вот рабочий пример отложенной загрузки фонового изображения в CSS.

See the Pen Lazy Loading background images in CSS by ImageKit.io (@imagekit_io) on CodePen.

Здесь следует отметить, что код Javascript для отложенной загрузки все тот же. Мы используем метод API Intersection Observer с фолбеком для слушателей событий. Самое интересное заключается в CSS.

Элемент с идентификатором bg-image имеет свойство background-image, определенное в CSS. Однако, когда к этому элементу добавляется класс lazy, в CSS мы переопределяем свойство
background-image и устанавливаем его none. Поскольку правило #bg-image в сочетании с классом .lazy имеет более высокий приоритет в CSS, чем просто #bg-image, браузер изначально применяет свойство background-image: none  к элементу. Когда мы прокручиваем страницу, Intersection Observer (или слушатели событий) обнаруживают, что изображение находится в области просмотра и удаляет класс . Это изменяет применяемое CSS правило и применяет фактическое свойство background-image к элементу и запускает загрузку фонового изображения.

Улучшение пользовательского опыта с отложенной загрузкой изображений

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

1. Использование правильных плейсхолдеров

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

Мы использовали такое решение в примере кода выше. Сплошной светло-серый цвет используется для всех наших фоновых изображений. Тем не менее, можно сделать лучше. Ниже приведены некоторые примеры использования заполнителей для изображений.

а. Преобладающий цвет изображения как плейсхолдер

Вместо использования фиксированного цвета для заполнителя изображения мы находим доминирующий цвет исходного изображения и используем его. Эта техника уже давно используется в результатах поиска изображений Google и Pinterest.

Этот способ может показаться сложным для реализации. Но есть простой способ — сначала нужно уменьшить изображение до 1 × 1 пикселя, а затем увеличить его до полного размера — это очень грубое приближение, но это простой способ получить единый доминирующий цвет. 

Видео демонстрации эффекта

б. Изображения низкого качества как плейсхолдер (Low quality image placeholder — LQIP)

Можно еще больше расширить идею использования цветового заполнителя. Вместо одного цвета можно использовать очень размытую версию исходного изображения в качестве заполнителя. Он не только выглядит лучше, он также дает пользователю некоторое представление о том, чего ожидать в реальном изображении, и дает представление о том, что происходит загрузка изображения. Это улучшает визуальное восприятия загрузки. Этот метод использовался Facebook и Medium.com для изображений на их сайтах и ​​в приложениях.

LQIPможет быть в 10 раз меньше исходного изображения и значительно улучшает визуальный опыт по сравнению с любой другой техникой-заполнителем.

Вот видео, демонстрирующее, как этот эффект работает для пользователя.

 Пример и код для использования техники LQIP здесь .

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

2. Добавление буферного времени для загрузки изображения

Когда мы рассматривали различные методы запуска загрузки изображения, мы проверяли момент времени, когда изображение входит в область просмотра, т.е. загрузка изображения запускается, когда верхний край заполнителя изображения совпадает с нижним краем области просмотра.

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

Хотя использование Intersection Observers для загрузки изображения или использование низкокачественных плейсхолдеров обеспечивает лучшую производительность при загрузке и удобство работы с пользователем, есть еще один простой прием, который можно использовать для обеспечения полной загрузки изображений при входе в область просмотра — использовать margin до точки запуска для изображений.

Решение 
Вместо загрузки изображения в тот момент, когда он точно входит в область просмотра, нужно загружать изображения на некотором расстоянии, например, 500 пикселей от входа в область просмотра. Это обеспечивает дополнительный запас времени между триггером загрузки и фактическим появлением изображения в окне.

С помощью API Intersection Observer можно использовать параметр `root` вместе с параметром` rootMargin` (работает как стандартное правило margin CSS). При использовании метода слушателя события вместо проверки равенства 0 разницы между краем изображения и краем области просмотра, мы можем использовать положительное число, чтобы добавить некоторый порог.

В данном примере для загрузки изображений используется пороговое значение 500 пикселей.

Как видно из видео ниже, при прокрутке, когда просматривается третье изображение, загружается 5-е изображение. Когда 4-е изображение попадает в поле зрения, 6-е изображение загружается. Таким образом, мы даем достаточно времени для полной загрузки изображений, и в большинстве случаев пользователь вообще не увидит заполнитель.

3. Как избежать смещения контента при использовании Lazy Load

Проблема 
Когда изображение отсутствует, браузер не знает размеров содержимого, которое должно отображаться во вложенном контейнере. И если мы не укажем его с помощью CSS, вмещающий контейнер не будет иметь размеров, то есть 0 x 0 пикселей. Затем, когда изображение загрузится, браузер изменит размер контейнера, чтобы он соответствовал изображению. Это внезапное изменение макета заставит другие элементы сместиться. Как показано в этой статье из журнала Smashing Magazine, это довольно неприятно наблюдать пользователю, поскольку контент перемещается внезапно при загрузке изображения.

Проблема 
Этого можно избежать, указав высоту и / или ширину для окружающего контейнера, чтобы браузер мог отрендерить контейнер изображения с известной высотой и шириной. Позже, когда изображение загрузится, то поскольку размер контейнера уже указан, и изображение идеально вписывается в него, остальная часть содержимого вокруг этого контейнера не перемещается.

4. Не используйте Lazy Load для всех изображений на странице

Еще одна ошибка, которую часто совершают разработчики — отложенная загрузка всех изображений на странице. Это может уменьшить начальное время загрузки страницы, но также ухудшит восприятие станицы пользователем, так как многие изображения даже в верхней части веб-страницы не будут отображаться до тех пор, пока не будет выполнен Javascript.

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

  • Любое изображение, которое присутствует в окне просмотра или в начале веб-страницы, не должно загружаться с отложенной загрузкой. Это относится к любому изображению заголовка, маркетинговому баннеру, логотипам и т. Д., Поскольку пользователь должен видеть их, как только страница загрузится. Кроме того, помните, что мобильные и настольные устройства имеют разные размеры и пропорции экрана и, следовательно, различное количество изображений на первом экране. Поэтому необходимо учитывать тип устройства, чтобы решить, какие ресурсы загружать сразу, а какие — через Lazy Load.
  • Любое изображение, которое находится немного вне области просмотра, должно быть загружено сразу. Это происходит по принципу, описанному выше — загружайте немного заранее.
  • Если страница не длинная, в один или два скролла, или если за пределами окна просмотра меньше 5 изображений, тогда можно вообще избежать отложенной загрузки. Это не обеспечит какого-либо существенного преимущества для конечного пользователя с точки зрения производительности. Дополнительный JS, который вы загружаете на страницу для включения отложенной загрузки, компенсирует выигрыш от отложенной загрузки такого небольшого количества изображений.

Зависимость от Javascript

Вся идея отложенной загрузки зависит от наличия возможностей выполнения Javascript в браузере пользователя. В то время как у большинства пользователей JavaScript включен по умолчанию, есть сценарии в которых или JavaScript может быть отключен, или браузер пользователя вообще его не поддерживает.

Вы можете показать сообщение о том, почему изображения не загружаются, и что нужно переключиться на современный браузер или включить Javascript. Или можно использовать тег noscript. Использование подхода с тегом <noscript> для таких пользователей имеет некоторые недостатки. 

Популярные Javascript библиотеки Lazy Load

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

yall.js — использует Intersection Observer и имеет фолбек к отложенной загрузке на основе событий. Поддерживает все основные типы элементов HTML, кроме фоновых изображения. Работает и на IE11 +.

lazysizes — очень популярный инструмент с обширным функционалом. Поддерживает адаптивные изображения и атрибуты srcset и sizes. Высокая производительность даже без Intersection Observer.

jQuery Lazy — простая библиотека отложенной загрузки на основе jquery.

WeltPixel Lazy Loading Enhanced — расширение Magento 2 для отложенной загрузки изображений

Magento Lazy Image Loader — расширение Magento 1.x для отложенной загрузки изображений

Shopify Lazy Image Plugin — Расширение Shopify для отложенной загрузки изображений.

WordPress A3 Lazy Load  —  плагин отложенной загрузки изображений для WordPress

Как проверить, работает ли Lazy Load на сайте?

После внедрения Lazy Load нужно проверить, работает ли она так, как задумано. Самый простой способ — открыть инструменты разработчика в браузере Chrome.

Перейдите на вкладку «Сеть»> «Изображения». Здесь, когда вы обновляете страницу в первый раз, должны загружаться только те изображения, которые должны быть загружены стразу. Затем, когда вы начнете прокручивать страницу вниз, будут запущены и загружены другие запросы на загрузку изображений. В этом представлении показано время загрузки изображения в виде водопада. Это поможет определить проблемы с загрузкой изображения.

Другой способ — запустить отчет о проверке Google Chrome Lighthouse на своей странице после внесения изменений и поиска предложений в разделе «Изображения за пределами экрана» .

Заключение

В этом руководстве мы рассмотрели практически все, что связано с отложенной загрузкой изображений. Lazy Load при правильной реализации значительно улучшит производительность загрузки страниц, уменьшит размер страницы и затраты на доставку за счет сокращения ненужных ресурсов, загружаемых заранее, при сохранении необходимого содержимого на странице.


2 Comments

  1. Цифровой11.02.2019

    А это нормально, что поисковые роботы увидят тег img без обязательного атрибута?
    Я у себя добавил в src прозрачную точку закодированную в base64. По крайней мере src теперь не пустой, и нет запросов к серваку. Только теперь осталась едва заметная проблема — до подгрузки изображения, они все квадратные…. и как интересно отнесутся поисковые роботы к тому, что все изображения изначально одинаковые.
    Ответьте, если знаете.

    Ответить
  2. Роман07.05.2019

    Уточните, какой из скриптов удобнее оптимизировать, чтобы сделать отложенную загрузку при горизонтальной прокрутке, типа Сториз. Спасибо.

    Ответить

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Scroll to top