Ленивая загрузка изображений

Библиотека Masonry используется для динамического и красивого расположения элементов на веб-странице, формируя сетку «кирпичной кладки». Одной из ключевых задач при работе с Masonry является оптимизация загрузки изображений, особенно при большом объёме контента. Ленивая загрузка позволяет подгружать изображения только тогда, когда они появляются в области видимости пользователя, снижая нагрузку на сеть и ускоряя первоначальное отображение страницы.

Для интеграции ленивой загрузки с Masonry важно понимать несколько моментов:

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

Подключение Masonry и базовая структура

HTML-структура сетки должна быть следующей:

<div class="grid">
  <div class="grid-item">
    <img data-src="image1.jpg" class="lazyload">
  </div>
  <div class="grid-item">
    <img data-src="image2.jpg" class="lazyload">
  </div>
  <div class="grid-item">
    <img data-src="image3.jpg" class="lazyload">
  </div>
</div>
  • grid — контейнер Masonry.
  • grid-item — каждый элемент сетки.
  • data-src — атрибут для ленивой загрузки, который содержит путь к изображению.

Подключение библиотеки Masonry:

<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>

Инициализация сетки:

const grid = document.querySelector('.grid');

const msnry = new Masonry(grid, {
  itemSelector: '.grid-item',
  columnWidth: '.grid-item',
  percentPosition: true,
  gutter: 10
});

Интеграция с ленивой загрузкой

Для ленивой загрузки можно использовать нативный атрибут loading="lazy" или библиотеку lazysizes. Пример с lazysizes:

<script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.3.2/lazysizes.min.js" async></script>
<img data-src="image1.jpg" class="lazyload">

Чтобы Masonry корректно пересчитывал сетку после загрузки каждого изображения, необходимо слушать событие load:

const images = grid.querySelectorAll('img.lazyload');

images.forEach(img => {
  img.addEventListener('load', () => {
    msnry.layout();
  });
});

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


Использование imagesLoaded для комплексной загрузки

Библиотека imagesLoaded идеально подходит для Masonry, особенно при ленивой загрузке. Она позволяет определить, когда все изображения внутри контейнера полностью загружены:

<script src="https://unpkg.com/imagesloaded@4/imagesloaded.pkgd.min.js"></script>

Пример использования:

imagesLoaded(grid, { background: true }, function() {
  msnry.layout();
});
  • background: true учитывает фоновые изображения через CSS.
  • Функция обратного вызова запускает перерасчет Masonry после полной загрузки всех элементов.

Для ленивой загрузки можно комбинировать с событием lazyloaded от lazysizes:

document.addEventListener('lazyloaded', function(e) {
  msnry.layout();
});

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

Несколько стратегий повышения эффективности ленивой загрузки с Masonry:

  1. Задание фиксированной высоты контейнера Если известна высота изображений, можно заранее задать размеры grid-item, чтобы Masonry правильно формировал сетку до полной загрузки изображений.

  2. Использование percentPosition и columnWidth Позволяет сетке адаптироваться к ширине окна и предотвращает «скачки» при загрузке контента.

  3. Отложенная инициализация Masonry В некоторых случаях полезно запускать Masonry после загрузки первого блока изображений:

    imagesLoaded(grid, function() {
      msnry.layout();
    });
  4. Комбинация с Intersection Observer Можно вручную подгружать изображения по мере появления элементов в viewport:

    const observer = new IntersectionObserver((entries, obs) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const img = entry.target;
          img.src = img.dataset.src;
          obs.unobserve(img);
        }
      });
    }, { threshold: 0.1 });
    
    images.forEach(img => observer.observe(img));

Работа с динамическим контентом

При добавлении новых элементов через AJAX или API важно:

  1. Добавлять новые элементы в Masonry с помощью append:
msnry.appended(newItems);
  1. Убедиться, что изображения новых элементов загружены перед пересчетом сетки:
imagesLoaded(newItems, function() {
  msnry.layout();
});
  1. Если используется ленивый загрузчик, привязывать обработчики событий load или lazyloaded к новым изображениям.

Практические рекомендации

  • Всегда обновлять Masonry после полной загрузки изображений, иначе сетка «ломается».
  • Для мобильных устройств и больших сеток лучше комбинировать lazyload с Intersection Observer для экономии ресурсов.
  • Использовать imagesLoaded для комплексных блоков с фоновыми изображениями и вложенными элементами.
  • Минимизировать размеры изображений и использовать современные форматы (WebP, AVIF) для ускорения загрузки и плавного отображения сетки.

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