Floating UI предоставляет мощные инструменты для динамического позиционирования всплывающих элементов (попапов, тултипов, дропдаунов) относительно целевых элементов на странице. Одним из ключевых механизмов является автоматическая смена стороны размещения (auto-flipping), которая гарантирует, что элемент всегда остаётся видимым в пределах окна браузера, даже если исходное положение перекрывается границами экрана.
1. reference и floating элементы
reference — это элемент, относительно которого
позиционируется всплывающее окно. floating — это сам
всплывающий элемент, который может изменять своё положение в зависимости
от доступного пространства.
2. middleware flip flip — это
middleware, встроенный в Floating UI, отвечающий за смену стороны
размещения. Он анализирует доступное пространство вокруг
reference и при необходимости меняет позицию
floating.
Пример использования middleware flip:
import { computePosition, flip, offset } from '@floating-ui/dom';
const reference = document.querySelector('#button');
const floating = document.querySelector('#tooltip');
computePosition(reference, floating, {
placement: 'top',
middleware: [offset(8), flip()]
}).then(({ x, y, placement }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`
});
});
В этом примере:
placement: 'top' — изначально всплывающее окно
расположено над кнопкой.offset(8) — отступ 8 пикселей от
reference.flip() — автоматически проверяет, помещается ли элемент
сверху, и при необходимости переключает на доступную сторону (например,
снизу, слева или справа).flip поддерживает несколько параметров, позволяющих
гибко управлять логикой смены стороны:
flip({
fallbackPlacements: ['bottom', 'right', 'left'],
boundary: document.body,
padding: 5
})
floating. По умолчанию это
viewport.boundary до floating.Пример с пользовательскими fallback-позициями:
computePosition(reference, floating, {
placement: 'top',
middleware: [
offset(10),
flip({
fallbackPlacements: ['bottom', 'right', 'left'],
padding: 12
})
]
});
Здесь floating будет пытаться сначала оставаться сверху,
затем проверять низ, правую и левую стороны до нахождения оптимального
положения.
Для динамически изменяющихся интерфейсов важно, чтобы смена стороны
происходила автоматически при изменении размера окна или прокрутке
страницы. Для этого используется autoUpdate:
import { autoUpdate } from '@floating-ui/dom';
autoUpdate(reference, floating, () => {
computePosition(reference, floating, {
placement: 'top',
middleware: [offset(10), flip()]
}).then(({ x, y }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`
});
});
});
autoUpdate отслеживает изменения позиции и размеров
элементов, автоматически вызывая пересчёт с middleware
flip. Таким образом, floating всегда остаётся
в видимой области.
Иногда требуется контролировать, как flip выбирает
сторону:
Только вертикальные варианты:
flip({ fallbackPlacements: ['bottom', 'top'] })Только горизонтальные варианты:
flip({ fallbackPlacements: ['right', 'left'] })Динамическое определение границы:
flip({ boundary: () => document.querySelector('#container') })Также можно комбинировать flip с другими middleware,
например shift, чтобы элемент дополнительно смещался внутри
видимой области при ограниченном пространстве:
computePosition(reference, floating, {
placement: 'top',
middleware: [offset(10), flip(), shift({ padding: 5 })]
});
shift корректирует положение floating, если
даже после flip оно частично выходит за границы окна.
Автоматическая смена стороны размещения в Floating UI обеспечивает корректное отображение всплывающих элементов в любой ситуации, делая интерфейс гибким и удобным без необходимости вручную вычислять позиции и размеры окна.