Viewport как boundary

В Popper.js boundary определяет область, за пределы которой всплывающий элемент (popper) не должен выходить. Одним из часто используемых вариантов является viewport — граница, ограниченная видимой областью окна браузера. Этот подход позволяет обеспечить корректное позиционирование элементов даже при динамических изменениях размеров окна или скроллинге страницы.

import { createPopper } from '@popperjs/core';

const reference = document.querySelector('#button');
const popper = document.querySelector('#tooltip');

createPopper(reference, popper, {
  modifiers: [
    {
      name: 'preventOverflow',
      options: {
        boundary: 'viewport',
      },
    },
  ],
});

В этом примере используется модификатор preventOverflow, который контролирует выход popper за границы. Опция boundary: 'viewport' указывает, что поппер не должен выходить за пределы видимой области окна браузера.


Механизм работы preventOverflow с viewport

Модификатор preventOverflow работает путем вычисления доступного пространства вокруг reference и корректировки позиции popper так, чтобы он полностью помещался внутри заданной границы. При использовании viewport алгоритм учитывает:

  • ширину и высоту окна браузера;
  • текущий скролл страницы (scrollTop, scrollLeft);
  • размеры popper и reference;
  • дополнительные смещения, заданные через padding.

Пример с добавлением padding:

createPopper(reference, popper, {
  modifiers: [
    {
      name: 'preventOverflow',
      options: {
        boundary: 'viewport',
        padding: 8,
      },
    },
  ],
});

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


Дополнительные параметры boundary

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

Массив сторон для ограничения:

createPopper(reference, popper, {
  modifiers: [
    {
      name: 'preventOverflow',
      options: {
        boundary: 'viewport',
        altAxis: true, // также ограничивает вторичную ось
      },
    },
  ],
});
  • altAxis: true — активирует проверку второй оси, что особенно полезно для вертикально или горизонтально ориентированных всплывающих элементов, предотвращая пересечение границ viewport.

Функция как boundary:

createPopper(reference, popper, {
  modifiers: [
    {
      name: 'preventOverflow',
      options: {
        boundary: (popperElement) => {
          return popperElement.ownerDocument.documentElement;
        },
      },
    },
  ],
});

В этом случае boundary вычисляется динамически, что дает возможность учитывать нестандартные контейнеры или кастомные ограничения.


Взаимодействие с другими модификаторами

Использование viewport как границы тесно связано с другими модификаторами:

  • flip — меняет сторону popper при нехватке места. При boundary viewport flip корректно реагирует на доступное пространство в окне.
  • offset — добавляет смещение от reference. При работе с viewport важно учитывать, что offset может вызывать пересечение границ, поэтому padding и altAxis помогают корректировать позицию.
  • hide — скрывает popper, если он полностью выходит за границы viewport. Полезно для элементов, которые не должны отображаться частично вне экрана.

Пример комплексной настройки:

createPopper(reference, popper, {
  modifiers: [
    {
      name: 'preventOverflow',
      options: {
        boundary: 'viewport',
        padding: 5,
        altAxis: true,
      },
    },
    {
      name: 'flip',
      options: {
        fallbackPlacements: ['top', 'bottom'],
      },
    },
    {
      name: 'offset',
      options: {
        offset: [0, 10],
      },
    },
  ],
});

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

Popper.js динамически пересчитывает позицию popper при изменении размеров viewport или скролле, если установлен модификатор eventListeners (включен по умолчанию). Это позволяет поддерживать boundary viewport даже при перемещении страницы или изменении размеров окна.

createPopper(reference, popper, {
  modifiers: [
    {
      name: 'eventListeners',
      options: {
        scroll: true,
        resize: true,
      },
    },
  ],
});

Таким образом, viewport как boundary обеспечивает адаптивность и корректное отображение popper, предотвращая выход за видимую область, даже в динамически изменяющихся интерфейсах.


Рекомендации по использованию viewport

  • Для всплывающих подсказок, тултипов и модальных меню рекомендуется всегда использовать viewport как boundary, чтобы элементы не обрезались.
  • Всегда добавляйте padding для эстетики и предотвращения наложений.
  • Используйте altAxis при сложной компоновке, чтобы контролировать обе оси.
  • Комбинируйте с flip и offset для гибкого позиционирования.

Viewport как boundary — основной инструмент Popper.js для ограничения всплывающих элементов в пределах видимой области, обеспечивающий предсказуемое и надежное поведение интерфейсов.