Floating UI — это современная библиотека для точного позиционирования всплывающих элементов, таких как диалоги, тултипы, меню и поповеры. Её ключевая задача — управление положением элемента относительно его reference element с учётом доступного пространства, перекрытий и динамических изменений DOM. Диалоги (dialogs) — один из самых распространённых сценариев использования.
Для корректного позиционирования необходимо различать два типа элементов:
import { computePosition, offset, flip, shift } from '@floating-ui/dom';
const reference = document.querySelector('#button');
const floating = document.querySelector('#dialog');
computePosition(reference, floating, {
placement: 'bottom-start',
middleware: [offset(8), flip(), shift({ padding: 5 })]
}).then(({ x, y }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`
});
});
Здесь используется три middleware:
placement определяет начальное расположение диалога
относительно reference. Возможные значения:
top, bottom, left, right — стандартные направления.
Добавление -start или -end управляет
выравниванием по оси:
bottom-start — диалог появляется снизу, левый край
совпадает с reference.right-end — диалог справа, нижний край совпадает с
reference.Правильный выбор placement зависит от визуальных
требований и доступного пространства.
Floating UI поддерживает цепочку middleware, которая позволяет комбинировать несколько правил позиционирования:
offset(value) — задаёт расстояние между reference и floating элементом. Может принимать число или функцию для динамических смещений.
flip(options) — меняет сторону, если на выбранной нет места. Настройки:
fallbackPlacements — массив альтернативных
позиций.padding — отступ от краёв видимой области.shift(options) — сдвигает элемент внутри видимой области.
padding гарантирует, что элемент не выйдет за границы
viewport.autoUpdate(reference, floating, callback) — автоматически пересчитывает позицию при изменении размеров reference, floating или окна.
import { autoUpdate } from '@floating-ui/dom';
autoUpdate(reference, floating, () => {
computePosition(reference, floating, {
placement: 'bottom',
middleware: [offset(10), flip(), shift({ padding: 10 })]
}).then(({ x, y }) => {
Object.assign(floating.style, { left: `${x}px`, top: `${y}px` });
});
});
Диалоги часто имеют изменяемое содержимое, что влияет на их размеры. Для корректного позиционирования необходимо:
autoUpdate или слушатели изменений
размеров (ResizeObserver).requestAnimationFrame для плавного позиционирования.computePosition(reference, floating, {
placement: 'top-end',
middleware: [
offset(12),
flip({ fallbackPlacements: ['bottom-end', 'top-start'] }),
shift({ padding: 8 })
]
}).then(({ x, y, placement }) => {
floating.style.transform = `translate3d(${x}px, ${y}px, 0)`;
floating.dataset.placement = placement;
});
Для React, Vue или Svelte существуют обёртки Floating UI, которые упрощают синхронизацию с состоянием компонента:
autoUpdate только при необходимости. Для
статичных диалогов достаточно однократного расчёта.requestAnimationFrame.Диалог может быть внутри overflow: hidden контейнера или
position: fixed модального окна. В таких случаях необходимо
учитывать:
strategy: ‘fixed’ | ‘absolute’ — определяет метод позиционирования.
fixed — позиционирование относительно viewport,
подходит для модальных окон.absolute — относительно ближайшего
offsetParent.Контейнеры с трансформациями (transform) влияют на
расчёт координат, поэтому Floating UI учитывает
getBoundingClientRect() всех предков.
Floating UI обеспечивает гибкое, динамическое позиционирование диалогов с учётом:
placement).offset).flip,
shift).autoUpdate).Корректная комбинация middleware позволяет создать диалог, который всегда остаётся видимым и точно выравнивается относительно reference, даже при сложных интерфейсных сценариях.