Vanilla JavaScript

Masonry — это библиотека для создания сеток с динамическим расположением элементов, часто называемая «Pinterest-style grid». Для использования в Vanilla JavaScript подключение может осуществляться несколькими способами:

  1. Через CDN:
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>
  1. Через npm (с последующей сборкой):
npm install masonry-layout

и импорт в проекте:

import Masonry from 'masonry-layout';

После подключения Masonry можно приступать к созданию сетки.


Основные параметры Masonry

При инициализации Masonry создается объект с набором конфигурационных опций:

const grid = document.querySelector('.grid');
const msnry = new Masonry(grid, {
  itemSelector: '.grid-item',
  columnWidth: 200,
  gutter: 10,
  fitWidth: true,
  percentPosition: true,
  horizontalOrder: false
});

Описание ключевых параметров:

  • itemSelector – селектор элементов сетки, которые будут располагаться в Masonry.
  • columnWidth – ширина колонки. Может быть числом или селектором элемента. Если задан элемент, Masonry подстраивает ширину колонок под его размер.
  • gutter – расстояние между колонками.
  • fitWidth – если true, сетка центрируется внутри родителя.
  • percentPosition – если true, Masonry использует процентные размеры для более гибкого отклика на изменение ширины контейнера.
  • horizontalOrder – если true, элементы будут располагаться по горизонтали, иначе по вертикали.

Основные методы Masonry

Masonry предоставляет методы для динамического управления сеткой:

  1. layout() – пересчитывает позиции элементов. Используется при изменении размеров или после добавления элементов:
msnry.layout();
  1. appended(elements) – добавляет новые элементы в сетку и пересчитывает их расположение:
const newItem = document.createElement('div');
newItem.classList.add('grid-item');
grid.appendChild(newItem);
msnry.appended(newItem);
  1. prepended(elements) – добавляет элементы в начало сетки.

  2. remove(elements) – удаляет элементы из Masonry:

msnry.remove(document.querySelectorAll('.grid-item.remove'));
msnry.layout();
  1. destroy() – уничтожает Masonry, возвращая DOM в исходное состояние:
msnry.destroy();

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

Для динамического контента, например, при подгрузке изображений, важно учитывать момент их загрузки, иначе Masonry рассчитает позиции некорректно. Используется событие imagesLoaded:

imagesLoaded(grid, function() {
  msnry.layout();
});

Пошаговая логика:

  1. Загружаются изображения внутри сетки.
  2. После полной загрузки вызывается метод layout() для корректного распределения элементов.

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


Поддержка адаптивности

Для адаптивной верстки рекомендуется использовать процентные размеры колонок и свойство percentPosition: true:

const msnry = new Masonry(grid, {
  itemSelector: '.grid-item',
  columnWidth: '.grid-sizer',
  percentPosition: true
});
  • Элемент .grid-sizer служит базовой единицей сетки.
  • Все .grid-item будут подстраиваться под размер .grid-sizer.

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


События Masonry

Masonry поддерживает несколько событий, которые полезны для интеграции с пользовательским интерфейсом:

  • layoutComplete – вызывается после завершения расчета сетки:
msnry.on('layoutComplete', function(items) {
  console.log('Сетка обновлена, элементов:', items.length);
});
  • removeComplete – после удаления элементов.
  • dragItemPositioned – используется при интеграции с Draggable для перетаскивания элементов.

Советы по оптимизации

  1. Минимизировать количество пересчетов: вызов layout() после каждой мелкой операции может замедлять страницу. Лучше использовать пакетное добавление через appended() или prepended().

  2. Использовать CSS-анимации с осторожностью: Masonry меняет transform для элементов, поэтому анимации высоты и позиционирования могут конфликтовать.

  3. Предварительная установка размеров элементов: если известно точное соотношение ширины и высоты, сетка будет рендериться быстрее и без визуальных «скачков».


Интеграция с другими библиотеками

  • imagesLoaded — для корректной работы с изображениями.
  • Draggabilly — для перетаскивания элементов в Masonry.

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

const msnry = new Masonry(grid, { itemSelector: '.grid-item', columnWidth: 200 });

const draggies = [];
grid.querySelectorAll('.grid-item').forEach(item => {
  const draggie = new Draggabilly(item);
  draggies.push(draggie);
  draggie.on('dragEnd', () => msnry.layout());
});

Варианты верстки

  • С фиксированными колонками — задаются ширина колонок и gutter, сетка равномерна.
  • С адаптивными колонками — используется элемент-сайзер и процентные позиции.
  • С динамическими элементами разной высоты — Masonry автоматически распределяет элементы, создавая «неровную» сетку без пустого пространства.

Примеры структуры HTML

<div class="grid">
  <div class="grid-sizer"></div>
  <div class="grid-item">Элемент 1</div>
  <div class="grid-item">Элемент 2</div>
  <div class="grid-item">Элемент 3</div>
</div>
  • .grid — контейнер Masonry.
  • .grid-sizer — базовый размер колонки.
  • .grid-item — элементы сетки.

Такой подход упрощает адаптивность и оптимизирует работу Masonry.


Дополнительные возможности

  • sort — Masonry не поддерживает сортировку по умолчанию, но можно комбинировать с JavaScript для изменения порядка элементов и вызова layout().
  • filter — скрытие и показ элементов с последующим layout().

Пример фильтрации:

document.querySelectorAll('.filter-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    const filter = btn.dataset.filter;
    grid.querySelectorAll('.grid-item').forEach(item => {
      item.style.display = item.classList.contains(filter) ? 'block' : 'none';
    });
    msnry.layout();
  });
});

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