Гид по технологиям

Ленивая загрузка изображений — как ускорить сайт с помощью loading="lazy" и Intersection Observer

5 min read Веб-разработка Обновлено 29 Dec 2025
Ленивая загрузка изображений: руководство
Ленивая загрузка изображений: руководство

Кодовый редактор открыт на ноутбуке

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

Ленивая загрузка (lazy loading) — это стратегия отложенной загрузки ресурсов (в основном изображений и видео), которая загружает их только тогда, когда они действительно нужны: когда элемент появляется в видимой области (viewport) или приближается к ней. Определение в одно предложение: метод откладывания загрузки несущественных ресурсов до момента их отображения пользователю.

Ключевые эффекты:

  • Меньше запросов и меньшая нагрузка на сеть при первоначальной загрузке.
  • Быстрее отображение первого контента (First Contentful Paint).
  • Экономия трафика для мобильных пользователей.

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

  • Более быстрая начальная загрузка страницы — пользователь видит контент быстрее и может начать взаимодействовать.
  • Улучшённая отзывчивость интерфейса при прокрутке — ресурсы подгружаются по ходу прокрутки.
  • Экономия трафика и ресурсов сервера (особенно при длинных страницах со множеством медиа).
  • Положительное влияние на SEO: скорость страницы — фактор ранжирования.

Important: Не все сценарии выигрывают от lazy loading. Для «above-the-fold» критичных изображений лучше загружать их сразу.

Быстрый пример: HTML с loading=”lazy”

Самый простой путь — использовать встроенный атрибут loading:


  
Фрагмент контента: крупное изображение 1
Фрагмент контента: крупное изображение 2
Фрагмент контента: крупное изображение 3

Атрибут loading=”lazy” сообщает браузеру отложить загрузку ресурса до тех пор, пока он не потребуется.

Начальная отрисовка страницы без ленивой загрузки

Улучшение: низкокачественный плейсхолдер и Intersection Observer

Нативный loading — отличное начало, но для большей совместимости и плавного перехода можно комбинировать низкокачественные плейсхолдеры (LQIP) и JavaScript на основе Intersection Observer. Идея: исходно загружается небольшое лёгкое изображение (webp/blur), а при появлении в viewport заменяем src на полноразмерный файл.

HTML-разметка с плейсхолдерами и data-src:

Низкокачественный плейсхолдер для изображения 1
Низкокачественный плейсхолдер для изображения 2
Низкокачественный плейсхолдер для изображения 3

Страница с низкокачественными изображениями в качестве основного src

JavaScript-логика с Intersection Observer (работающая и в современных браузерах):

"use strict";

// Выбираем все изображения, помеченные loading="lazy"
const lazyImages = document.querySelectorAll('img[loading="lazy"]');

// Опции observer'а: немного заранее подгружаем (rootMargin) и порог видимости
const observerOptions = {
  root: null, // viewport
  rootMargin: '200px 0px', // подгружаем, когда изображение в 200px от viewport
  threshold: 0.01 // считаем элемент пересечённым при минимальной видимости
};

const observer = new IntersectionObserver((entries, obs) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      if (img.dataset && img.dataset.src) {
        img.src = img.dataset.src; // заменяем плейсхолдер на полноценное изображение
        // Можно дополнительно удалить data-src или добавить класс loaded
        img.removeAttribute('data-src');
      }
      obs.unobserve(img); // перестаём наблюдать за загруженным элементом
    }
  });
}, observerOptions);

// Запускаем наблюдение для каждого изображения
lazyImages.forEach(img => {
  observer.observe(img);
});

Советы:

  • Используйте rootMargin, чтобы подгружать изображения заранее и избежать «вспышек» при быстром скролле.
  • threshold=0.01 позволяет начинать загрузку при очень малой доле видимости.
  • После загрузки снимайте наблюдение для экономии ресурсов.

Обработка фоновых изображений и элемент div

Для фоновых картинок (background-image) также можно использовать Intersection Observer. Пример:

Контент
const lazyBackgrounds = document.querySelectorAll('.lazy-bg');
lazyBackgrounds.forEach(bg => {
  observer.observe(bg);
});

// В callback observer'а при isIntersecting заменить background-image на data-bg

Адаптивные изображения (srcset и picture)

Для экономии трафика стоит отдавать оптимизированные варианты изображений через srcset и picture. Пример сочетания srcset и lazy loading:


  
  Адаптивное изображение

В JavaScript при lazy-замене нужно копировать data-srcset в srcset, а не только src.

Взаимодействие с SEO и доступностью

  • Доступность: всегда указывайте alt с описанием изображения или пустой alt=”” для декоративных элементов.
  • SEO: поисковики индексируют ленивые изображения, если они появляются в DOM и имеют корректные атрибуты; используйте server-side rendering для критичных элементов.
  • Prerender/SSR: для страниц с критичным «above-the-fold» контентом отдавайте основные изображения с сервера, а остальное можно лениво подгружать.

Notes: Для экранных читалок alt важен — он описывает визуальный контент.

Совместимость с браузерами и полифиллы

  • Нативный атрибут loading поддерживают большинство современных браузеров, но не все старые версии.
  • Intersection Observer поддерживается в современных браузерах; для старых потребуется полифилл.
  • Рекомендуется проверять поддержку через Can I Use и при необходимости подключать полифилл с CDN для IE11/старых Android-браузеров.

Тестирование и критерии приёмки

Критерии приёмки:

  • Изображения above-the-fold загружаются сразу без значимой задержки.
  • Изображения, появляющиеся при прокрутке, подгружаются своевременно и без визуальных «миганий».
  • Для каждого img есть корректный alt.
  • После перехода на высококачественный src, исходный low-src не остается в data-src.
  • Нет ошибок в консоли (CORS, 404 и т.д.).

Тест-кейсы:

  1. Открыть страницу с медленным соединением — проверить, что начальная загрузка стала быстрее.
  2. Быстро проскроллить страницу — убедиться, что изображения не «прыгают» и подгружаются заранее.
  3. Отключить JS — убедиться, что критичные изображения всё ещё видимы (грейсфул деградация).
  4. Тестировать с экранным читалкой — alt читается корректно.
  5. Проверить в старых браузерах с подключённым полифиллом.

Когда ленивый подход не подходит

  • Маленькие страницы с 1–2 изображениями: выигрыш минимален, усложнение не нужно.
  • Критичные визуальные элементы в верхней части страницы: задержка загрузки ухудшит UX.
  • Когда внешняя аналитика или бот-парсеры требуют немедленной загрузки всех изображений.

Альтернативные подходы:

  • Использовать CDN с адаптивной трансформацией изображений (автоматически отдаёт нужный размер).
  • Библиотеки: lazysizes, lozad.js — готовые решения с полифиллами и дополнительным функционалом.

Руководство внедрения (мини-SOP)

  1. Проинвентаризируйте изображения страницы: пометьте критичные для initial render.
  2. Для некритичных добавьте loading=”lazy” и, по желанию, data-src с плейсхолдером.
  3. Подготовьте LQIP (маленькие webp/blur) для плавного UX.
  4. Добавьте Intersection Observer с rootMargin для предзагрузки.
  5. Тестируйте на разных устройствах и сетях.
  6. Отслеживайте метрики: FCP, LCP, CLS, TTFB.
  7. При необходимости добавьте полифилл для старых браузеров.

Чек-лист для релиза

  • Критичные изображения — не ленивые.
  • Все img имеют alt.
  • Нет 404 у изображений.
  • JS-переключение src работает для srcset/picture.
  • Произведено кроссбраузерное тестирование.

Эвристики и ментальные модели

  • Правило 80/20: оптимизируйте первые 20% видимого контента — они дают 80% первого впечатления.
  • Предзагрузка: лучше подгружать немного раньше (rootMargin), чем догонять загрузку уже в поле зрения.
  • Плейсхолдеры улучшают восприятие скорости даже при длительной загрузке.

Отладка и распространённые проблемы

  • Проблема: изображение не загружается при прокрутке. Причина: observer.observe не вызван или querySelector не нашёл элементов.
  • Проблема: быстрое прокручивание вызывает «пустые» места. Решение: увеличить rootMargin или использовать eager загрузку для блоков, где пользователь часто останавливается.
  • Проблема: Cumulative Layout Shift (CLS) из-за отсутствия указанных размеров. Решение: всегда задавайте width/height или используйте aspect-ratio/placeholders.

Краткое резюме

Ленивая загрузка изображений — простой и эффективный способ улучшить скорость сайта и экономию трафика. Начните с native loading=”lazy”, затем добавьте Intersection Observer для более контролируемой подгрузки, LQIP и поддержку srcset для адаптивности. Обязательно тестируйте на реальных устройствах и учитывайте доступность.

Часто задаваемые вопросы

Работает ли loading=”lazy” во всех браузерах?

Не во всех. Большинство современных браузеров поддерживают этот атрибут, но для старых версий требуется полифилл.

Нужно ли использовать low-quality placeholders?

Не обязательно, но они заметно улучшают визуальное восприятие при медленной сети и уменьшают эффект «прыжка» изображения.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как безопасно путешествовать с фотоаппаратом
Путешествия

Как безопасно путешествовать с фотоаппаратом

Отключить веб-камеру в Windows 11
Безопасность

Отключить веб-камеру в Windows 11

FaceTime на Mac: выбрать камеру, микрофон, динамики
macOS

FaceTime на Mac: выбрать камеру, микрофон, динамики

Как добавить туман в фотографии в Luminar AI
фото редактирование

Как добавить туман в фотографии в Luminar AI

Редактирование фото со смартфона в Luminar AI
Фото

Редактирование фото со смартфона в Luminar AI

Luminar AI: стильные портреты быстро
Фото

Luminar AI: стильные портреты быстро