Fallback-позиции — это альтернативные варианты размещения всплывающего элемента (popper), которые используются, если основное положение невозможно применить из-за ограничений пространства. Библиотека Popper.js автоматически анализирует доступную область и переключается между позициями, обеспечивая корректное отображение элемента без обрезания или выхода за границы контейнера.
Ключевая задача fallback-механизма — сохранить видимость и доступность popper-элемента независимо от изменений размеров окна, прокрутки или ограничений родительских контейнеров.
При задании основного размещения через свойство
placement (например, "top"), Popper.js
пытается разместить элемент строго в указанной позиции. Если вычисления
показывают, что элемент выходит за границы viewport или
clipping-контейнера, активируется модификатор flip.
Модификатор flip:
Простейший пример:
createPopper(referenceElement, popperElement, {
placement: 'top',
modifiers: [
{
name: 'flip',
},
],
});
В этом случае при нехватке места сверху popper может автоматически переместиться вниз.
По умолчанию Popper.js использует логическую последовательность fallback-позиций, основанную на противоположных направлениях:
top → bottomleft → rightbottom → topright → leftОднако поведение можно полностью контролировать через параметр
fallbackPlacements.
Пример настройки:
createPopper(referenceElement, popperElement, {
placement: 'top',
modifiers: [
{
name: 'flip',
options: {
fallbackPlacements: ['right', 'bottom', 'left'],
},
},
],
});
В этом случае порядок будет строго следующим:
top (основной)rightbottomleftPopper.js оценивает каждую позицию по следующим критериям:
boundary)Алгоритм:
Если ни одна позиция не подходит полностью, выбирается наименее проблемная.
Fallback-позиции напрямую зависят от области, в пределах которой
разрешено размещение. Эта область задаётся через параметр
boundary.
Пример:
{
name: 'flip',
options: {
boundary: 'viewport',
},
}
Возможные значения:
viewport — границы окна браузераclippingParents — ближайшие ограничивающие
контейнерыЕсли boundary слишком ограничен, fallback-позиции будут переключаться чаще.
flip часто используется вместе с
preventOverflow. Первый отвечает за смену позиции, второй —
за корректировку внутри текущей позиции.
Пример комбинирования:
createPopper(referenceElement, popperElement, {
placement: 'top',
modifiers: [
{
name: 'flip',
options: {
fallbackPlacements: ['bottom', 'right'],
},
},
{
name: 'preventOverflow',
options: {
padding: 8,
},
},
],
});
Поведение:
topbottom, затем rightpreventOverflow
подстраивает положениеПорядок в массиве fallbackPlacements критически важен.
Popper.js не пытается «оптимизировать» список — он строго следует
заданной последовательности.
Неудачный пример:
fallbackPlacements: ['left', 'right', 'bottom']
Если пространство справа идеально, но слева мало места — всё равно
сначала проверяется left.
Оптимальный подход:
Если fallbackPlacements не задан, Popper генерирует
список автоматически, основываясь на основной позиции.
Пример:
placement: 'top-start'
Автоматические fallback:
bottom-starttop-endbottom-endЭто особенно важно для вариаций с -start и
-end.
Fallback-позиции могут включать вариации выравнивания:
fallbackPlacements: [
'top-start',
'top-end',
'bottom-start',
'bottom-end'
]
Это позволяет более точно контролировать положение относительно reference-элемента.
Особенности:
start выравнивает по началу (лево или верх)end — по концу (право или низ)Иногда требуется полностью отключить fallback или сильно его ограничить.
Пример отключения:
{
name: 'flip',
enabled: false,
}
Пример ограничения:
fallbackPlacements: []
В этом случае popper остаётся в основной позиции даже при переполнении.
Существует несколько подходов к формированию fallback-цепочек:
1. Противоположная позиция
['bottom']
Минимальный вариант — только зеркальная позиция.
2. Перпендикулярные направления
['right', 'left']
Используется при ограничении по вертикали.
3. Полный цикл
['top', 'right', 'bottom', 'left']
Максимальная гибкость, но больше вычислений.
4. Приоритет UX
['bottom', 'bottom-start', 'bottom-end']
Ориентация на привычное поведение интерфейса.
Чем больше fallback-позиций:
Оптимизация:
Отсутствие fallbackPlacements при сложной верстке
В сложных layout (например, внутри scroll-контейнеров) стандартного поведения недостаточно.
Неправильный порядок
Логически неверный порядок приводит к «скачкам» popper.
Игнорирование boundary
Без явного указания границ поведение может быть непредсказуемым.
Слишком длинный список
Избыточные fallback-позиции ухудшают производительность без заметной пользы.
createPopper(button, tooltip, {
placement: 'top',
modifiers: [
{
name: 'flip',
options: {
fallbackPlacements: [
'bottom',
'right',
'left'
],
padding: 8,
},
},
{
name: 'preventOverflow',
options: {
boundary: document.body,
},
},
],
});
Поведение:
bodyОпция altBoundary позволяет учитывать альтернативный
контейнер при вычислениях:
{
name: 'flip',
options: {
altBoundary: true,
},
}
Используется, когда popper и reference находятся в разных контекстах позиционирования.
rootBoundary задаёт глобальные ограничения:
{
name: 'flip',
options: {
rootBoundary: 'document',
},
}
Варианты:
viewportdocumentЭто влияет на то, как рассчитываются fallback-позиции в масштабируемых или прокручиваемых документах.
Fallback-позиции пересчитываются при:
Popper использует систему обновлений (update lifecycle), чтобы автоматически адаптировать позицию.
Иногда требуется динамически менять fallback:
const isMobile = window.innerWidth < 768;
createPopper(ref, pop, {
modifiers: [
{
name: 'flip',
options: {
fallbackPlacements: isMobile
? ['bottom']
: ['right', 'left'],
},
},
],
});
Это позволяет адаптировать поведение под разные устройства.
Ключевые параметры модификатора flip:
{
name: 'flip',
options: {
fallbackPlacements: [...],
boundary: ...,
rootBoundary: ...,
padding: ...,
altBoundary: ...,
}
}
Грамотная настройка этих параметров обеспечивает: