Popper.js обеспечивает динамическое позиционирование всплывающих элементов относительно целевых элементов на странице. Ключевой компонент управления позиционированием — стратегия детекции и предотвращения выхода за пределы видимой области (overflow detection). В стандартной конфигурации Popper.js использует встроенные методы обнаружения границ видимой области и корректирует позицию поппера. Однако для сложных интерфейсов стандартных настроек может быть недостаточно, что делает актуальным применение альтернативных стратегий детекции.
preventOverflow с кастомными параметрамиМодуль preventOverflow контролирует, чтобы поппер не
выходил за пределы указанных контейнеров. По умолчанию
boundariesElement установлен на
'clippingParents', что означает использование ближайших
элементов с ограничением видимости. Для сложных макетов можно изменить
эту стратегию:
const popperInstance = Popper.createPopper(referenceElement, popperElement, {
modifiers: [
{
name: 'preventOverflow',
options: {
boundary: document.querySelector('#custom-container'),
padding: 10,
tether: true,
},
},
],
});
Ключевые параметры:
boundary — элемент, относительно которого проверяется
переполнение.padding — внутренний отступ, чтобы поппер не прилипал к
краю.tether — ограничение движения поппера, предотвращающее
выход за пределы границы при любых вычислениях.flip с расширенными настройкамиМодуль flip позволяет менять позицию поппера, если
исходная позиция приводит к выходу за границы видимой области. Помимо
стандартной стратегии, можно задать свой набор допустимых
вариантов позиций:
const popperInstance = Popper.createPopper(referenceElement, popperElement, {
placement: 'bottom',
modifiers: [
{
name: 'flip',
options: {
fallbackPlacements: ['top', 'right', 'left'],
padding: 5,
boundary: 'viewport',
},
},
],
});
fallbackPlacements — массив альтернативных позиций,
которые Popper попробует использовать при переполнении.boundary может быть 'viewport',
'scrollParent' или кастомный элемент.padding задает минимальное расстояние до границ.computeStyles и
onUpdateДля интерфейсов с динамическим контентом иногда необходимо полностью
контролировать вычисление позиции поппера. Popper.js позволяет
переопределить расчёт стилей через модификатор
computeStyles:
const popperInstance = Popper.createPopper(referenceElement, popperElement, {
modifiers: [
{
name: 'computeStyles',
options: {
adaptive: false, // Отключение адаптивного позиционирования
gpuAcceleration: false,
},
},
{
name: 'customDetection',
enabled: true,
phase: 'main',
fn({ state }) {
if (state.rects.popper.top < 0) {
state.styles.popper.top = '10px';
}
if (state.rects.popper.left < 0) {
state.styles.popper.left = '10px';
}
},
},
],
});
Такой подход позволяет реализовать собственные алгоритмы проверки выхода за пределы, учитывая сложные правила макета или анимации.
flip и preventOverflow для продвинутой
детекцииДля максимальной гибкости часто комбинируют flip и
preventOverflow:
const popperInstance = Popper.createPopper(referenceElement, popperElement, {
placement: 'bottom-start',
modifiers: [
{ name: 'flip', options: { fallbackPlacements: ['top-end', 'right-start'] } },
{ name: 'preventOverflow', options: { padding: 8, tether: true } },
],
});
flip пытается найти лучшую позицию при
переполнении.preventOverflow корректирует положение, чтобы поппер не
вылез за границы контейнера.При изменении размеров целевого элемента или поппера стандартные
стратегии могут быть недостаточны. Для таких случаев Popper.js
предоставляет событие update:
popperInstance.forceUpdate(); // Принудительное пересчитывание позиции
Можно подписаться на изменение размеров через
ResizeObserver и вызывать forceUpdate,
обеспечивая динамическую детекцию:
const ro = new ResizeObserver(() => {
popperInstance.forceUpdate();
});
ro.observe(referenceElement);
ro.observe(popperElement);
Этот метод позволяет избежать «проваливания» поппера за пределы видимой области при изменении контента или размеров окна.
Popper.js допускает использование функции в boundary
модификатора preventOverflow для более точного
контроля:
const popperInstance = Popper.createPopper(referenceElement, popperElement, {
modifiers: [
{
name: 'preventOverflow',
options: {
boundary: (popper, reference) => {
const rect = reference.getBoundingClientRect();
return {
top: rect.top - 20,
left: rect.left - 20,
right: rect.right + 20,
bottom: rect.bottom + 20,
};
},
},
},
],
});
Это позволяет реализовать нестандартные стратегии детекции, учитывая внутренние отступы, перекрытия или анимации соседних элементов.
Альтернативные стратегии детекции обеспечивают:
Такой подход делает Popper.js эффективным инструментом для создания сложных, адаптивных UI-компонентов, где стандартная детекция недостаточна.