Вложенные сетки

Packery — это библиотека для динамической укладки элементов в сетку с возможностью перетаскивания, перестройки и адаптивного размещения блоков. Одной из сложных, но мощных концепций является использование вложенных сеток, когда внутри одного элемента основной сетки располагается собственная независимая сетка. Такой подход позволяет создавать многоуровневые интерфейсы, где каждая область может иметь свои правила укладки и поведения.


Создание вложенной сетки

Вложенная сетка — это обычный контейнер Packery, размещённый внутри элемента родительской сетки. Основной принцип работы:

  1. Родительская сетка и вложенная инициализируются независимо друг от друга.
  2. Позиционирование элементов во вложенной сетке не влияет напрямую на координаты родителя, но может потребоваться обновление родительской сетки при изменении размеров вложенной.

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

<div class="grid-parent">
  <div class="grid-item">
    <div class="grid-child">
      <div class="child-item">1</div>
      <div class="child-item">2</div>
      <div class="child-item">3</div>
    </div>
  </div>
  <div class="grid-item">Элемент родителя 2</div>
  <div class="grid-item">Элемент родителя 3</div>
</div>
  • .grid-parent — контейнер родительской сетки.
  • .grid-item — элементы родителя.
  • .grid-child — контейнер вложенной сетки.
  • .child-item — элементы вложенной сетки.

Инициализация Packery для вложенной сетки

// Родительская сетка
const parentGrid = new Packery('.grid-parent', {
  itemSelector: '.grid-item',
  gutter: 10
});

// Вложенная сетка
const childGrid = new Packery('.grid-child', {
  itemSelector: '.child-item',
  gutter: 5
});

Ключевые моменты:

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

Обновление размеров родителя при изменении вложенной сетки

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

childGrid.on('layoutComplete', function() {
  parentGrid.layout(); // пересчитывает позиции родителя
});
  • layoutComplete — событие Packery, которое срабатывает после перестройки внутренней сетки.
  • Вызов parentGrid.layout() обеспечивает правильное размещение родительских элементов, учитывая новые размеры вложенной сетки.

Перетаскивание элементов во вложенной сетке

Packery поддерживает Draggabilly для drag-and-drop. Вложенные сетки могут иметь собственные правила перетаскивания:

const draggies = [];

childGrid.getItemElements().forEach(function(itemElem) {
  const draggie = new Draggabilly(itemElem);
  childGrid.bindDraggabillyEvents(draggie);
  draggies.push(draggie);
});
  • Элементы родительской сетки остаются независимыми.
  • Можно комбинировать перетаскивание родителя и дочерних элементов, чтобы создавать многоуровневые интерактивные интерфейсы.

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

Для добавления новых элементов во вложенную сетку используется метод appended:

const newItem = document.createElement('div');
newItem.className = 'child-item';
newItem.textContent = 'Новый элемент';
childGrid.appended(newItem);
childGrid.layout();
parentGrid.layout(); // обновление родителя при необходимости
  • appended добавляет элемент в Packery, не перезаписывая всю сетку.
  • Обновление родителя необходимо, если новый элемент увеличивает размер контейнера.

Советы по производительности

  1. Минимизировать пересчёты родительской сетки. Обновление родителя после каждого изменения вложенной сетки может быть дорогим. Лучше использовать debounce или вызывать layout только после завершения серии изменений.
  2. Использовать percentPosition, если сетка должна быть адаптивной. Это особенно важно для вложенных сеток, чтобы элементы корректно масштабировались.
  3. Ограничивать количество вложенных уровней. Packery хорошо работает с 1–2 уровнями вложенности; большее количество может вызвать просадки производительности.

Взаимодействие с CSS Grid и Flexbox

Packery может быть использован поверх CSS Grid или Flexbox, но для вложенных сеток рекомендуется:

  • Вложенная сетка должна иметь фиксированный или относительно предсказуемый контейнер.
  • Убедиться, что стили position: relative для контейнера и position: absolute для элементов вложенной сетки применены корректно.
  • Избегать конфликтов между автоматической укладкой Packery и встроенными правилами CSS.

Использование Packery с анимацией

Packery поддерживает плавную анимацию перестановки элементов через CSS transitions. Для вложенных сеток:

.grid-child .child-item {
  transition: transform 0.4s, width 0.4s, height 0.4s;
}
  • Анимация не только улучшает UX, но и помогает визуально отслеживать изменения в многослойной сетке.
  • transition можно применять отдельно для вложенных и родительских элементов, чтобы избежать визуального конфликта.

Вложенные сетки в Packery позволяют создавать сложные, гибкие интерфейсы с динамическим размещением элементов. Основные правила — раздельная инициализация, обновление родителя при изменении вложенной сетки, и корректное управление перетаскиванием и анимацией. Такой подход обеспечивает полноценную управляемую и адаптивную систему визуальных блоков на веб-странице.