Веб‑разработчики постоянно ищут способы уменьшить время загрузки страниц, снизить трафик и улучшить Core Web Vitals. Одна из самых эффективных техник – lazy loading изображений. Современный способ реализовать её – использовать Intersection Observer API, который позволяет загружать изображения только тогда, когда они становятся видимыми в окне браузера. Это не только экономит пропускную способность, но и ускоряет отображение контента, повышая ранжирование в поисковых системах.
Разбор задачи
Многие сайты загружают все изображения сразу, независимо от того, видит ли пользователь их в данный момент. При большом количестве медиафайлов это приводит к повышенному расходу трафика и задержкам в отображении. Lazy loading позволяет отложить загрузку до момента, когда пользователь прокручивает страницу и нужное изображение входит в область видимости. Intersection Observer API предоставляет точный механизм отслеживания пересечения элемента с окном просмотра, что делает реализацию простой и надёжной без сторонних библиотек.
Пошаговое решение
Для начала добавляем атрибут data-src к тегам <img>, в котором хранится реальный URL изображения. Затем создаём наблюдатель, который будет реагировать на появление элемента в зоне видимости. При срабатывании callback‑функция заменяет src на значение data-src, инициируя загрузку. После загрузки можно удалить наблюдателя, чтобы не тратить ресурсы. Такой подход гарантирует, что изображения загружаются только при необходимости, улучшая скорость первой визуальной отрисовки (FCP) и уменьшает общий объём передаваемых данных.
Рабочий код
// 1. Выбираем все изображения, которые будем lazy‑load
const lazyImages = document.querySelectorAll('img[data-src]');
// 2. Создаём Observer с нужными опциями
const observer = new IntersectionObserver((entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
// 3. Заменяем src на data-src
img.src = img.dataset.src;
// 4. Убираем наблюдение, чтобы не переобновлять
obs.unobserve(img);
}
});
}, {
root: null, // viewport
rootMargin: '200px', // подгружаем заранее
threshold: 0.1
});
// 5. Запускаем наблюдение для каждого изображения
lazyImages.forEach(img => observer.observe(img));
// 6. Обработка ошибок (fallback)
observer.observe = function() { console.warn('IntersectionObserver не поддерживается.'); };
Типичные ошибки
1. Неправильный селектор – выбираем все img, а не только с data-src. Это приводит к лишней работе скрипта.
2. Отсутствие rootMargin – изображения начинают грузиться только когда полностью входят в viewport, что ухудшает UX.
3. Не отключать Observer – наблюдение за элементом после загрузки продолжается, расходуя ресурсы.
4. Синхронный src заменяющий data-src – если скрипт исполняется до того, как браузер начал загрузку, картинка может загрузиться дважды.
FAQ
1. Что делать, если браузер не поддерживает Intersection Observer?
Можно подключить polyfill или использовать fallback‑скрипт с scroll‑событиями. Однако polyfill может существенно увеличить размер bundle.
2. Как оптимизировать изображение перед lazy loading?
Используйте современные форматы (WebP, AVIF), уменьшайте размер и применяйте srcset для разных плотностей пикселей. Это снизит трафик и ускорит отображение.
3. Нужно ли добавлять loading="lazy" в теги img вместе с Intersection Observer?
Да, это совместимая стратегия: атрибут loading покрывает старые браузеры, а Observer обеспечивает более гибкий контроль.
Заключение
Lazy loading с Intersection Observer – простое решение, повышающее производительность и SEO. Выполните чек‑лист:
- ✅ Добавьте
data-srcвместоsrcв тегиimg. - ✅ Установите
rootMarginоколо 200 px. - ✅ Отключайте Observer после загрузки.
- ✅ Подключайте polyfill только при необходимости.
- ✅ Оптимизируйте изображения: форматы, размеры,
srcset.
