Пакетное добавление элементов

Библиотека Masonry предназначена для создания динамических сеток с равномерным распределением элементов по колонкам, наподобие “мозаики”. Одним из ключевых приёмов оптимизации работы с Masonry является пакетное добавление элементов. Этот подход позволяет добавлять сразу несколько элементов в сетку, минимизируя пересчёт расположения и улучшая производительность.


Метод appended для пакетного добавления

Masonry предоставляет метод .appended() для интеграции новых элементов в уже существующую сетку. Он принимает NodeList, массив DOM-элементов или отдельный элемент, который был создан динамически.

Пример:

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

const newElements = document.createElement('div');
newElements.innerHTML = `
  <div class="grid-item">1</div>
  <div class="grid-item">2</div>
  <div class="grid-item">3</div>
`;
const items = newElements.querySelectorAll('.grid-item');

msnry.appended(items);

Ключевой момент: .appended() автоматически пересчитывает позиции только для добавленных элементов, что гораздо эффективнее, чем полное обновление сетки через .layout() после каждого добавления.


Использование insert и append с фрагментами

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

Пример с DocumentFragment:

const fragment = document.createDocumentFragment();

for (let i = 0; i < 10; i++) {
  const div = document.createElement('div');
  div.className = 'grid-item';
  div.textContent = `Элемент ${i+1}`;
  fragment.appendChild(div);
}

grid.appendChild(fragment);

const newItems = fragment.querySelectorAll('.grid-item');
msnry.appended(newItems);

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


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

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

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

imagesLoaded(grid, function() {
  const newItems = document.querySelectorAll('.grid-item-new');
  msnry.appended(newItems);
});

Рекомендация: всегда использовать проверку загрузки изображений перед вызовом .appended(), особенно если элементы содержат картинки, так как Masonry рассчитывает позиции исходя из фактических размеров элементов.


Анимация и плавное добавление

Для визуальной плавности можно комбинировать .appended() с CSS-анимациями. Элементы добавляются с прозрачностью 0, а после добавления Masonry обновляет сетку и активируется анимация.

Пример:

.grid-item {
  opacity: 0;
  transform: translateY(20px);
  transition: all 0.4s ease;
}

.grid-item.show {
  opacity: 1;
  transform: translateY(0);
}
const newItems = document.querySelectorAll('.grid-item-new');
newItems.forEach(item => item.classList.add('show'));
msnry.appended(newItems);

Эффект: элементы появляются плавно и не нарушают текущий порядок сетки.


Работа с большим количеством элементов

При добавлении десятков или сотен элементов важно:

  1. Использовать DocumentFragment для минимизации операций с DOM.
  2. Вызывать .appended() один раз для всех новых элементов, а не по одному.
  3. Убедиться, что все изображения или динамический контент загружены перед добавлением.

Такая оптимизация предотвращает “мерцание” сетки и снижает нагрузку на рендер браузера.


Пример комплексного подхода

fetch('/api/new-items')
  .then(res => res.json())
  .then(data => {
    const fragment = document.createDocumentFragment();
    data.forEach(itemData => {
      const div = document.createElement('div');
      div.className = 'grid-item grid-item-new';
      div.innerHTML = `<img src="${itemData.img}" alt="">${itemData.text}`;
      fragment.appendChild(div);
    });

    grid.appendChild(fragment);
    const newItems = fragment.querySelectorAll('.grid-item-new');

    imagesLoaded(grid, function() {
      msnry.appended(newItems);
      newItems.forEach(item => item.classList.add('show'));
    });
  });

Преимущества такого подхода:

  • Минимум пересчётов Masonry.
  • Полная интеграция с динамически загруженными изображениями.
  • Возможность применять анимации к пакетным элементам.

Пакетное добавление элементов в Masonry — это сочетание оптимизации DOM, правильного времени вызова .appended() и аккуратного управления визуальными эффектами. Следование этим правилам позволяет строить высокопроизводительные сетки даже с большим количеством динамического контента.