Packery — это библиотека для динамического
размещения элементов на веб-странице с использованием принципа «гибкой
сетки» (masonry layout). Она позволяет управлять расположением блоков
разной высоты и ширины, обеспечивая плотную компоновку без лишних
промежутков. Основной объект библиотеки — это экземпляр
Packery, который создается на контейнере с элементами.
const grid = document.querySelector('.grid');
const pckry = new Packery(grid, {
itemSelector: '.grid-item',
gutter: 10
});
itemSelector — CSS-селектор для элементов, которые
будут упорядочиваться.gutter — отступ между элементами.originLeft и originTop — определяют
начальную точку отсчета (по умолчанию слева и сверху).Packery позволяет динамически добавлять или удалять элементы без
пересоздания всей сетки. Для добавления используется метод
appended:
const newItem = document.createElement('div');
newItem.classList.add('grid-item');
grid.appendChild(newItem);
pckry.appended(newItem);
Для удаления элементов применяется метод remove:
const itemToRemove = document.querySelector('.grid-item:first-child');
pckry.remove(itemToRemove);
pckry.layout();
Важно: после удаления необходимо вызвать
layout(), чтобы пересчитать позиции остальных
элементов.
Packery интегрируется с библиотекой Draggabilly для
перетаскивания элементов. Создание draggable-элементов выглядит
следующим образом:
const draggies = [];
document.querySelectorAll('.grid-item').forEach((item) => {
const draggie = new Draggabilly(item);
pckry.bindDraggabillyEvents(draggie);
draggies.push(draggie);
});
bindDraggabillyEvents — связывает Packery с
Draggabilly, чтобы при перемещении элементов сетка обновлялась
автоматически.Packery поддерживает гибкую конфигурацию сетки:
columnWidth — фиксирует ширину
колонки. Может быть числом или селектором элемента.rowHeight — устанавливает высоту
строки (редко используется, чаще работает на основе реальной высоты
элементов).percentPosition — включение вычисления
позиций в процентах, полезно для адаптивного дизайна.Пример адаптивной сетки с процентными позициями:
const pckry = new Packery(grid, {
itemSelector: '.grid-item',
columnWidth: '.grid-sizer',
percentPosition: true
});
Packery предоставляет несколько событий для управления жизненным циклом сетки:
layoutComplete — срабатывает после завершения
компоновки.removeComplete — после удаления элементов.dragItemPositioned — после завершения перетаскивания
элемента.Пример подписки на событие:
pckry.on('layoutComplete', (items) => {
console.log('Сетка обновлена', items.length, 'элементов');
});
Для больших сеток с сотнями элементов важно не рендерить все DOM-элементы сразу. Виртуализация позволяет отображать только видимые элементы, улучшая производительность. Packery не имеет встроенной виртуализации, но её можно реализовать вручную:
IntersectionObserver.remove и пересчет layout().Пример интеграции с IntersectionObserver:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
const item = entry.target;
if (entry.isIntersecting) {
grid.appendChild(item);
pckry.appended(item);
} else {
pckry.remove(item);
}
});
}, { root: grid, threshold: 0.1 });
document.querySelectorAll('.grid-item').forEach(item => observer.observe(item));
transform: translate3d) для анимации, чтобы снизить
нагрузку на браузер.layout() — вызывать его только
после добавления/удаления блока, а не при каждом изменении позиции.gutter и columnWidth так,
чтобы уменьшить количество пересчётов сетки при ресайзе окна.Packery можно использовать с React, Vue и Angular, но важно помнить:
mounted, updated и
beforeDestroy, чтобы корректно управлять жизненным циклом
сетки.Пример с React:
useEffect(() => {
const pckry = new Packery(gridRef.current, { itemSelector: '.grid-item' });
return () => pckry.destroy();
}, []);
destroy() освобождает ресурсы и удаляет обработчики
событий.Packery поддерживает CSS-анимации для плавного перемещения элементов.
Для этого достаточно задавать переходы для свойства
transform и width/height:
.grid-item {
transition: transform 0.4s ease, width 0.4s ease, height 0.4s ease;
}
requestAnimationFrame для синхронизации с пересчетом
сетки.Виртуализация в Packery требует сочетания стратегий:
IntersectionObserver для определения
видимых элементов.appended
и remove.layout() для повышения
производительности.Такой подход позволяет создавать крупные, динамичные сетки с сотнями элементов, сохраняя отзывчивость интерфейса и плавность анимации.