Floating UI — это современная библиотека для управления позиционированием плавающих элементов в веб-приложениях. Она заменяет устаревшие решения вроде Popper.js и предоставляет гибкий API для динамического расчёта координат элементов относительно якоря. Основная задача библиотеки — точное позиционирование всплывающих элементов (tooltip, popover, dropdown, меню и др.) с учётом ограничений видимой области и смещений.
Floating UI строится на двух ключевых понятиях:
Библиотека использует функцию вычисления позиции
computePosition(reference, floating, options), которая
возвращает объект с координатами { x, y } и дополнительной
информацией о размещении (placement,
middlewareData).
import { computePosition, offset, flip } 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 }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`
});
});
В этом примере offset(8) добавляет отступ от якоря, а
flip() автоматически переворачивает элемент, если он не
помещается на экране.
Middleware — ключевой инструмент для расширения логики расчёта позиции. Библиотека предоставляет набор готовых middleware и позволяет создавать свои:
Middleware вызываются последовательно и могут модифицировать
финальные координаты x и y. Понимание порядка
вызова важно при комбинировании нескольких middleware.
computePosition(reference, floating, {
placement: 'right',
middleware: [
offset(10),
flip({ fallbackPlacements: ['left', 'bottom'] }),
shift({ padding: 5 })
]
});
Для работы в React Floating UI предлагает хук
useFloating, который инкапсулирует вычисление позиции и
управление состоянием:
import { useFloating, offset, flip, shift } from '@floating-ui/react-dom';
function Tooltip({ children, label }) {
const { x, y, reference, floating, strategy } = useFloating({
placement: 'top',
middleware: [offset(5), flip(), shift()]
});
return (
<>
<button ref={reference}>{children}</button>
<div
ref={floating}
style={{ position: strategy, top: y ?? 0, left: x ?? 0 }}
>
{label}
</div>
</>
);
}
Здесь strategy задаёт способ позиционирования:
absolute или fixed. В React контексте Floating
UI автоматически пересчитывает координаты при изменении DOM и размеров
элементов.
Micro-frontends требуют, чтобы плавающие элементы корректно работали в разных фреймах или Shadow DOM. Floating UI поддерживает:
getBoundingClientRect() и передачи кастомного
контейнера.Пример использования в Shadow DOM:
const shadowRoot = hostElement.attachShadow({ mode: 'open' });
const button = document.createElement('button');
shadowRoot.appendChild(button);
const tooltip = document.createElement('div');
shadowRoot.appendChild(tooltip);
computePosition(button, tooltip, { placement: 'bottom' })
.then(({ x, y }) => {
tooltip.style.transform = `translate(${x}px, ${y}px)`;
});
Floating UI минимизирует количество перерасчётов позиции через:
autoUpdate — функция, которая
подписывает элементы на события изменения размеров, скролла или
трансформаций:import { autoUpdate } from '@floating-ui/dom';
autoUpdate(reference, floating, () => {
computePosition(reference, floating, { middleware: [offset(5), flip()] })
.then(({ x, y }) => {
Object.assign(floating.style, { left: `${x}px`, top: `${y}px` });
});
});
flip, shift, size и
arrow для создания адаптивных всплывающих интерфейсов.middleware в порядке от смещения к
адаптивному изменению позиции
(offset → flip → shift → arrow).autoUpdate при динамическом контенте,
особенно если родительский фрейм или DOM элементы могут изменять
размер.fallbackPlacements для flip,
чтобы элементы никогда не вылезали за пределы видимой области.Floating UI позволяет создавать интеллектуально позиционируемые плавающие элементы, подходящие для сложных веб-интерфейсов с микрофронтендами, iframe и динамическими контейнерами.