Мультипозиционирование

Popper.js предоставляет мощные инструменты для управления положением элементов интерфейса, таких как всплывающие подсказки, модальные окна или тултипы. Мультипозиционирование позволяет элементу адаптивно менять своё расположение в зависимости от доступного пространства на странице, предотвращая обрезание контента или выход за границы окна браузера.

В основе работы Popper.js лежат позиционные стратегии (positioning strategies) и модификаторы (modifiers). Для мультипозиционирования ключевыми являются:

  • placement — начальное предпочтительное положение элемента относительно его родителя (top, bottom, left, right) с возможными вариациями (-start, -end).
  • flip — модификатор, позволяющий автоматически менять позицию, если выбранная изначально вызывает коллизии с границами контейнера или окна.
  • preventOverflow — модификатор, предотвращающий выход элемента за границы окна или указанного контейнера.

Использование модификатора flip

Модификатор flip управляет динамическим изменением позиции поппера. Он проверяет доступное пространство и выбирает альтернативное размещение из списка приоритетов.

Пример конфигурации:

const popperInstance = Popper.createPopper(referenceElement, popperElement, {
  placement: 'top',
  modifiers: [
    {
      name: 'flip',
      options: {
        fallbackPlacements: ['right', 'bottom', 'left'],
      },
    },
  ],
});

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

  • placement: 'top' — первоначальная позиция поппера.
  • fallbackPlacements — массив альтернативных позиций, которые Popper будет использовать при нехватке пространства.
  • Поппер будет последовательно проверять позиции из массива и автоматически перемещаться на первую доступную.

Работа модификатора preventOverflow

Модификатор preventOverflow обеспечивает, что поппер не выйдет за пределы контейнера. Он учитывает размеры окна, прокрутку и отступы.

Пример:

const popperInstance = Popper.createPopper(referenceElement, popperElement, {
  modifiers: [
    {
      name: 'preventOverflow',
      options: {
        boundary: 'viewport',
        padding: 8,
      },
    },
  ],
});

Особенности конфигурации:

  • boundary может принимать значения viewport, document, DOM-элемент или массив элементов. Определяет, внутри каких границ нужно удерживать поппер.
  • padding — минимальное расстояние от границы.

Комбинация flip и preventOverflow

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

const popperInstance = Popper.createPopper(referenceElement, popperElement, {
  placement: 'bottom-start',
  modifiers: [
    { name: 'flip', options: { fallbackPlacements: ['top-start', 'right-start'] } },
    { name: 'preventOverflow', options: { boundary: 'viewport', padding: 10 } },
  ],
});

Здесь поппер будет стремиться оставаться снизу, но при нехватке места сначала попробует верхнее положение, затем правое, и никогда не выйдет за границы окна с учётом отступа 10px.


Контроль приоритетов позиций

Popper.js позволяет задать полный порядок приоритетов позиций через массив fallbackPlacements или модифицировать его динамически. Это особенно полезно для адаптивных интерфейсов с ограниченным пространством, например:

const popperInstance = Popper.createPopper(referenceElement, popperElement, {
  placement: 'right',
  modifiers: [
    {
      name: 'flip',
      options: {
        fallbackPlacements: ['bottom', 'top', 'left'],
        padding: 5,
      },
    },
  ],
});

Popper проверяет позиции в указанном порядке, и если ни одна не подходит, применяет ближайшую оптимальную.


Обработка динамических изменений контента

Мультипозиционирование должно учитывать изменения размеров или положения элементов после рендеринга. Для этого используется метод update():

popperInstance.update();

Вызывается при:

  • изменении размеров поппера или целевого элемента;
  • изменении структуры DOM вокруг поппера;
  • изменении размера окна или контейнера.

Использование кастомных ограничителей

Для сложных интерфейсов можно задать собственные ограничения границ через модификатор preventOverflow:

const popperInstance = Popper.createPopper(referenceElement, popperElement, {
  modifiers: [
    {
      name: 'preventOverflow',
      options: {
        boundary: document.querySelector('#custom-container'),
        tether: true,
      },
    },
  ],
});
  • tether управляет тем, насколько поппер может «выпирать» за границы контейнера, обеспечивая гибкую привязку.
  • boundary указывает кастомный контейнер вместо окна браузера.

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

  • Начальная placement должна соответствовать основной логике интерфейса.
  • Всегда комбинируйте flip и preventOverflow для адаптивного поведения.
  • Используйте fallbackPlacements для контроля порядка позиций.
  • Вызывайте update() при динамическом изменении контента или размеров.
  • При необходимости ограничивайте поппер кастомными контейнерами для сложных макетов.

Эти подходы делают Popper.js универсальным инструментом для мультипозиционирования элементов в любых пользовательских интерфейсах.