Ленивая загрузка без JavaScript: нативный loading="lazy" и его ограничения

Браузеры давно умеют откладывать загрузку изображений без единой строки скрипта. Один атрибут в теге — и картинки запрашиваются с сервера только тогда, когда пользователь до них доскроллил. Звучит как готовое решение для любого сайта. На практике атрибут работает не так прямолинейно, а в некоторых ситуациях приносит больше вреда, чем пользы. Разберём механику, правила подключения и реальные ограничения.

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

Атрибут loading="lazy" появился в спецификации HTML в 2019 году. Chrome поддерживает его с версии 77 (сентябрь 2019), Firefox — с версии 75 (апрель 2020), Safari — с версии 15.4 (март 2022), Edge — с версии 79.

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

Атрибут принимает три значения:

  • loading="lazy" — отложенная загрузка, браузер сам решает, когда начинать запрос.
  • loading="eager" — приоритетная загрузка без откладывания. Обычно соответствует стандартному поведению браузера.
  • loading="auto" — стратегию выбирает браузер; поведение не специфицировано и различается в разных браузерах, использовать не рекомендуется.

Применяется атрибут к тегам <img> и <iframe>. Браузеры, которые не поддерживают атрибут, просто игнорируют его и загружают ресурс немедленно — ничего не сломается, просто отложенная загрузка не сработает.

Как правильно подключить

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

<img src="photo.jpg" alt="Описание фото" width="800" height="600" loading="lazy">

Для iframe синтаксис тот же:

<iframe src="https://www.youtube.com/embed/ID" width="560" height="315" loading="lazy"></iframe>

Почему важно резервировать место под изображение

Отсутствие заранее зарезервированного места под изображение — один из самых частых источников проблем при внедрении lazy loading. Когда браузер не знает размеры изображения до его загрузки, он не резервирует место в макете. Как только картинка загружается, она сдвигает соседние элементы — страница перестраивается на глазах у пользователя. Этот эффект называется Cumulative Layout Shift (CLS) и входит в набор метрик Core Web Vitals, характеризующих качество пользовательского опыта.

С атрибутами width и height браузер заранее вычисляет соотношение сторон и резервирует нужное место в потоке документа. Изображение загружается — страница не смещается. Явные размеры нужны при любой ленивой загрузке, нативной или через JS.

Если изображения выводятся через CSS с max-width: 100%, атрибуты всё равно нужно ставить в оригинальных пикселях — браузер сам пересчитает пропорции под контейнер.

Первый вьюпорт: что браузер загружает сразу

Атрибут loading="lazy" не означает, что все изображения на странице загружаются лениво. Браузер анализирует начальное положение каждого элемента, и изображения в зоне первого экрана загружает немедленно, игнорируя атрибут. Это правильное поведение: пользователь должен видеть контент без задержки сразу после открытия страницы.

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

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

Порог загрузки: почему им нельзя управлять

Браузер начинает загружать отложенное изображение не в момент, когда оно появляется в видимой области, а заранее — когда оно приближается к ней на некоторое расстояние. Это расстояние называется порогом загрузки (distance threshold).

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

На практике это означает, что нельзя точно предсказать, когда именно начнётся загрузка. Если нужен точный контроль — например, начинать загрузку строго при пересечении элементом границы экрана — нативного атрибута недостаточно. Здесь нужен IntersectionObserver в JavaScript.

SEO-риск: отложенные изображения и индексация

Поисковые роботы рендерят страницы иначе, чем обычные браузеры. Googlebot использует вьюпорт высотой около 10 000 пикселей — это означает, что на большинстве страниц он «видит» все изображения разом, и нативный loading="lazy" для него практически не создаёт проблем. Однако Googlebot не имитирует скролл и не реагирует на пользовательские события, поэтому изображения, которые в JS-реализации загружаются по клику или свайпу, он не получит.

Яндекс-бот поддерживает рендеринг JavaScript, но его поведение при обходе длинных страниц менее предсказуемо, а задержки между сканированием и рендерингом бывают значительными. Если робот не запросил изображение, он не увидит его alt-текст, не проиндексирует файл и не включит его в поиск по картинкам.

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

Поддержка iframe: история с задержкой

Поддержка loading="lazy" для <iframe> появилась позже, чем для изображений, и не одновременно во всех браузерах. Chrome поддерживает её с версии 77 (2019), Safari — с версии 16.4 (март 2023), Firefox добавил поддержку в версии 121 (декабрь 2023). Сейчас атрибут работает во всех актуальных браузерах.

Встроенные карты и видео (Яндекс.Карты, YouTube, VK Видео) — хороший кандидат для ленивой загрузки. iframe с картой или плеером загружает десятки дополнительных ресурсов, и если он находится ниже первого экрана, отложенная загрузка даёт ощутимый выигрыш в скорости.

   На страницах с тяжёлыми iframe (карты, видеоплееры, сторонние виджеты) ленивая загрузка нередко даёт заметное улучшение показателей загрузки и пользовательского опыта.

Когда нативного решения недостаточно

Нативный loading="lazy" покрывает большинство типовых задач, но есть сценарии, где он не подходит:

  • Нужен точный контроль над моментом загрузки — например, начинать строго при пересечении элементом границы вьюпорта.
  • Изображения подгружаются динамически через JS (бесконечный скролл, слайдеры, табы) — браузер не знает о них при первичном разборе HTML, и атрибут не учитывается.
  • Нужно показывать placeholder или анимацию до появления изображения.
  • Поддержка старых браузеров, где атрибут не работает, критична для проекта.

В этих случаях используют IntersectionObserver API — он даёт полный контроль над порогом, работает с динамически добавляемыми элементами и позволяет подключать любые обработчики к событиям пересечения. Нативный loading="lazy" при этом можно оставить в разметке как запасной вариант: в браузерах без JavaScript он отложит загрузку самостоятельно.

Связка с fetchpriority

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

<img
src="hero.webp"
width="1200"
height="630"
fetchpriority="high"
alt="Главный баннер">

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

Чек-лист внедрения

  • Не ставить loading="lazy" на изображения первого экрана — баннер, логотип, первое фото в статье.
  • Всегда указывать width и height — иначе страница будет смещаться при загрузке и вырастет CLS.
  • Для контентных изображений, которые должны индексироваться, учитывать риск пропуска Яндекс-ботом.
  • Для iframe с картами и видео атрибут ставить — выигрыш в скорости ощутимый, рисков мало.
  • Проверить результат в Lighthouse: метрика LCP не должна вырасти после внедрения, CLS должна снизиться или остаться на нуле.
Апсолямов Михаил
Автор — Михаил Апсолямов
Занимаюсь SEO‑продвижением сайтов в Хабаровске: от разработки стратегии до вывода в топ-10 Яндекса и Google. Опыт работы — с 2009 года.
наверх