Артём Мáлков

Lazy Load 2.0 – ленивая (отложенная) загрузка изображений на JavaScript

17 мар27 комм

Если вам доводилось сталкиваться с PageSpeed Insights – инструментом по анализу скорости загрузки сайта от компании Google, то вы могли наблюдать в нем сообщение вида «Отложите загрузку скрытых изображений». Что это и зачем Google рекомендует внедрить эту технологию на ваш сайт?

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

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

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

Первые версии плагина, автором которого, кстати говоря, является Мика Туупола, были реализованы с использованием jQuery. В этой же статье я покажу вам свежую версию плагина (Remastered, как называет ее сам автор) на чистом JavaScript.

Инструкция по установке Lazy Load 2.0 на сайт

Итак, все как обычно.

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

2. Далее в секцию HEAD на всех страницах вашего сайта подключите ранее загруженный скрипт:

<script src="/js/lazyload.js"></script>

Не забывайте корректно прописывать адрес до скрипта на вашем сайте.

3. Перед закрывающим тегом </body> вы вставляете скрипт вызова плагина и стиль для скрытия отложенных изображений при отключенном в браузере JavaScript:

<noscript>
		
	<style>
		img[data-src] {
			display: none !important;
		}
	</style>

</noscript>

<script>

	let images = document.querySelectorAll("img");

	lazyload(images);

</script>

«img» в скрипте означает, что «лениво» загружаться будут все изображения. Можно поставить ограничение в виде определенного CLASS или ID.

4. Затем (не обязательно, но желательно), в секцию HEAD (обязательно в нее, а не в другое место или отдельный файл стилей) вставьте следующие правила:

<style>
	img[data-src] {
		opacity: 0 !important;
	}

	img[src] {
		opacity: 1 !important;
	}
</style>

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

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

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

Стандартная конструкция вставки изображения в HTML выглядит так:

<img class="logo_style" src="/logo-big.png" alt="Наш логотип" />

Различия с кодом ваших изображений могут быть лишь в разного рода атрибутах. Главное здесь то, что ранее используемый атрибут «src» вы заменяете на «data-src»:

<img class="logo_style" data-src="/logo-big.png" alt="Наш логотип" />

<noscript>

	<img class="logo_style" src="/logo-big.png" alt="Наш логотип" />

</noscript>

Оригинальное изображение в теге <noscript> (как и сам тег) не обязательно, но желательно. Оно будет отображаться в том случае, если на стороне пользователя (в его браузере) отключена работа JavaScript.

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

По желанию можно не удалять атрибут «src» и прописывать в нем ссылку до превью (уменьшенной копии):

<img class="logo_style" src="/logo-small.png" data-src="/logo-big.png" alt="Наш логотип" />

<noscript>

	<img class="logo_style" src="/logo-big.png" alt="Наш логотип" />

</noscript>

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

Предвидя ваш вопрос «У меня куча изображений на сайте, мне что теперь, все руками изменять?», отвечу – я придумал один способ, как можно автоматизировать этот процесс.

Автоматическое изменение кода изображений для Lazy Load 2.0

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

Для этого на все страницы вашего сайта (если вы используете CMS, то в главный файл, чаще всего это файл index.php) в самый верх вставьте код:

function lazyload_img($buffer) {

	return preg_replace("#<img([^>]*) src=['\"](.*?)['\"]([^>]*)>#", '<img$1 data-src="$2"$3><noscript><img$1 src="$2"$3></noscript>', $buffer);
	
} 

ob_start("lazyload_img");

Обратите внимание: на вашем сайте должна быть поддержка PHP. Приведенный скрипт ищет все изображения на странице и заменяет им атрибут «src» на «data-src» + добавляет оригинальное изображение в теге <noscript>.

Это все, что я хотел рассказать вам касаемо плагина «Lazy Load». Если остались вопросы – пишите об этом в комментариях под данной статьей.

Файл
Размер
Ссылка
lazyload.zip
1,79 Kb
Скачать с сервера
Рекомендуем к просмотру
Ещё один вариант отложенной загрузки скриптов на jQuery/JavaScript
Посты
Как сделать экран загрузки (preloader) на сайте на JavaScript?
Статьи и советы
Выполнение (запуск) скрипта после загрузки страницы на jQuery/JavaScript
Посты
27
комментариев
Форма комментирования этого поста скрыта. Авторизуйтесь, чтобы расширить привилегии гостевого посещения и получить необходимую помощь от сообщества Pandoge.
    • 2
    2
      •  Пользователь
    2 ноя в 14:02

    скрипт- убийца. Поставил скрипт первый раз на сайт(dle) с вкупе со скриптом что подменяет src на data-src. Проверил - работает.

    Через день захожу на сайт а все картинки скриптом скрыты (чтото там глюкнуло) - траф ополовинился. Ну ок думаю, случайность. Подождал пока траф восстановится и рискнул поставить еще раз, на этот раз сам скрипт не падал, но захожу с утра в стату - траф успел упасть на 30%. В гугл консоли если сделать "проверка урл" и потом сделать скрин сайта, так как видит его бот, то скрин без картинок..тоесть бот картинок получется, что не видит (незнаю насколько это характерно именно для этого скрипта или для всех лази-лоад скриптов, но факт).

    Про то как проверять лази-лоад (в частности проверкой урл)

    https://developers.google.com/search/docs/advanced/javascript/lazy-loading?hl=ru

      • 3
      2
        •  Пользователь
      3 ноя в 20:27

      в дополнеие к предыдущему комменту про скрипт-убийцу. На самом деле не убийца, но скрипт убил счетчик liveinternet, который выводится через img. Потоу траф "рухнул"

      • 2
      1066
        •  Команда Pandoge
      6 ноя в 03:45

      Serg R, здравствуйте! Спасибо за комментарий.

      Чтобы исключить изображение из отложенной загрузки можно воспользоваться следующей вставкой:

      (?!LINK_IMG)

      Где LINK_IMG - экранированный путь (полный или его начало) до исключаемого изображения.

      На примере счётчика LI (ссылка - //counter.yadro.ru/hit?t45.6;r) это будет выглядеть следующим образом:

      return preg_replace("#<img([^>]*) src=['\"](?!\/\/counter\.yadro\.ru)(.*?)['\"]([^>]*)>#", '<img$1 data-src="$2"$3><noscript><img$1 src="$2"$3></noscript>', $buffer);
    • 3
    30
      •  Проверенный
    26 окт в 22:45

    Можно ли прикрутить это например к классу lazy

    class="lazy" или class="lazy-load"

      • 2
      1066
        •  Команда Pandoge
      27 окт в 16:13

      Sergey, конечно.

      В скрипте:

      let images = document.querySelectorAll("img");

      замените на:

      let images = document.querySelectorAll(".lazy");

      В стилях (все совпадения):

      img[data-src]

      на:

      img.lazy[data-src]

      и

      img[src]

      на:

      img.lazy[src]
      • 2
      30
        •  Проверенный
      28 окт в 07:35

      Артём Мáлков, а для автоматического изменения кода изображения как будет)?

      function lazyload_img($buffer) {
      
      	return preg_replace("#<img.lazy([^>]*) src=['\"](.*?)['\"]([^>]*)>#", '<img.lazy$1 data-src="$2"$3><noscript><img.lazy$1 src="$2"$3></noscript>', $buffer);
      	
      } 
      
      ob_start("lazyload_img");

      ну примерно я сделал это

      • 2
      30
        •  Проверенный
      6 ноя в 09:19

      Sergey, я ведь правильно написал?

      Или это не изменяется?

      • 2
      1066
        •  Команда Pandoge
      7 ноя в 01:23

      Sergey, не совсем. Сегодня постараюсь прислать рабочий вариант.

      • 2
      30
        •  Проверенный
      7 ноя в 07:09

      Артём Мáлков, спасибо большое:)

      • 2
      1066
        •  Команда Pandoge
      изменено 7 ноя в 14:57

      Sergey, попробуйте так (простой и не совсем точный вариант):

      function lazyload_img($buffer) {
      
      	return preg_replace_callback(
      		"#<img([^>]*) src=['\"](.*?)['\"]([^>]*)>#",
      		function($img) {
      		
      			if(preg_match("#class=['\"](.*)lazy(.*)['\"]#", $img[0])) {
      				
      				return '<img'.$img[1].' data-src="'.$img[2].'"'.$img[3].'><noscript><img'.$img[1].' src="'.$img[2].'"'.$img[3].'></noscript>';
      
      			}
      
      			return $img[0];
      
      		},
      		$buffer
      	);
      	
      } 
      
      ob_start('lazyload_img');

      Неточный, потому что классов у изображения может быть несколько и проверку наличия нужного я осуществляю через выражение:

      #class=['\"](.*)lazy(.*)['\"]#

      Оно просто проверяет присутствие частицы lazy, то есть, если у вас будет, например, класс nolazy - скрипт все отработает. Варианта тут три.

      1. Это задать такой класс, который точно не будет входить в название другого класса.

      2. Указать только один класс у нужных изображений.

      3. Указать ID (он, как вы можете знать, прописывается один в элементе).

      В третьем случае, часть:

      #class=['\"](.*)lazy(.*)['\"]#

      нужно заменить на:

      #id=['\"](.*)lazy(.*)['\"]#

      Ну и понаблюдайте, не тормозит ли этот скрипт сайт.

      • 3
      30
        •  Проверенный
      9 ноя в 17:15

      Артём Мáлков, Спасибо попробую

      • 3
      30
        •  Проверенный
      18 ноя в 18:58

      Артём Мáлков, мне кажется что не работает

      вроде добавляет loading="lazy", но отложенная загрузка не происходит

      • 2
      1066
        •  Команда Pandoge
      19 ноя в 02:19

      Sergey, хм.. Ошибки есть в консоли? Можно ссылку на сайт?

    • 4
    1
      •  Пользователь
    12 авг в 16:32

    Здравствуйте. подскажите пожалуйста как вот этот пункт - Автоматическое изменение кода изображений для Lazy Load 2.0 - заставить автоматически менять не на всей странице, а в определённом блоке?

    ну например div-у можно назначить id уникальный и тем самым автоматическое изменение будет срабатывать внутри данного id.

    думаю такое решение будет уникальным и правильнее. а так получается вся страница автоматически меняется и в том числе ненужное! и кривит тем самым шаблон и другие элементы...

      • 2
      1066
        •  Команда Pandoge
      22 авг в 21:22

      Раф, здравствуйте! Не думаю, что решение будет "правильнее". Вы просто можете вручную изменить принцип вывода информации в этом блоке с учетом рекомендаций описанных в статье.

    • 3
    1
      •  Пользователь
    15 фев в 17:03

    Добрый день, подскажите, подключил Lazy Load на своем сайте. Во всех браузерах все отлично работает, а в internet explorer 11 не подгружаются изображения. В чем может быть проблема?

      • 2
      1066
        •  Команда Pandoge
      16 фев в 17:20

      Сергей, здравствуйте!

      Можете показать сайт?

    • 3
    1
      •  Пользователь
    4 дек в 03:34

    Привет. Если в браузере отключен java script, то на месте картинок остаются пустые места.

      • 2
      1066
        •  Команда Pandoge
      4 дек в 16:21

      Владимир Степанов, здравствуйте.

      Обновил статью. smiley

    • 2
    1
      •  Пользователь
    16 авг в 18:08

    Артем, все делал по вашей инструкции. Спасибо! А как для background image (фоновая картинка с параллаксом в блоке на лендинге) это реализовать?

    пример кода:

    <div class="bg parallax-bg" data-top-bottom="transform:translate3d(0px, 25%, 0px)" data-bottom-top="transform:translate3d(0px, -25%, 0px)"></div>

    и второй вопрос можно ли использовать для iframe, как тогда в этом случае прописать пункт 3 вашей инструкции?

      • 2
      1066
        •  Команда Pandoge
      16 авг в 19:34

      Виктор Медведев, Здравствуйте. Насколько я знаю, этот вариант скрипта работает только с изображениями вставленными через тег img.

      Позже рассмотрим более функциональный вариант.

      • 2
      6
        •  Пользователь
      7 янв в 15:55

      Артём Мáлков,

      А будет инструкция как сделать для Dle тоже lazy Load?

      • 2
      1066
        •  Команда Pandoge
      7 янв в 23:31

      Шаген, для DLE делается все так же с совмещением этого хака - https://www.pandoge.com/haki/minifikaciya-szhatie-ishodnogo-koda-html-v-dle-na-php

    • 2
    26
      •  Проверенный
    17 июн в 21:31

    Есть разница этого плагина и того что использует DLE?

      • 2
      1066
        •  Команда Pandoge
      18 июн в 01:06

      Артём Ройзман, я думаю, что особой разницы нет. Вариант из статьи более универсальный. А так, это не единственная существующая реализация Lazy Load.

    • 2
    1
      •  Пользователь
    1 июн в 00:27

    Заметил что этот Lazy Load с изображениями формата jpg не работает. С png без проблем. Можно как то исправить ?

      • 2
      1066
        •  Команда Pandoge
      1 июн в 20:44

      Роман, покажите сайт где наблюдается проблема.

      Но насколько я знаю, он работает со всеми популярными форматами.

Подняться наверх
«Pandoge» - помощник вебмастера