Floating UI — это современная библиотека для управления позиционированием всплывающих элементов в браузере. Она обеспечивает точное и предсказуемое размещение тултипов, дропдаунов, поповер-меню и других плавающих компонентов. Основные различия в API Floating UI проявляются в подходе к конфигурации, модификаторам и стратегиям позиционирования.
computePosition и её особенностиОсновным API является функция computePosition, которая
заменяет привычные методы вроде getBoundingClientRect и
вручную написанные логики для позиционирования.
import { computePosition, offset, flip, shift } from '@floating-ui/dom';
const reference = document.querySelector('#button');
const floating = document.querySelector('#tooltip');
computePosition(reference, floating, {
placement: 'top',
middleware: [offset(8), flip(), shift({ padding: 5 })],
}).then(({ x, y }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`,
});
});
Ключевые моменты:
placement определяет начальное направление появления
плавающего элемента (top, bottom,
left, right) с возможными вариациями
(-start, -end).middleware — массив функций, которые могут
модифицировать позицию перед финальным рендером.x и
y, а также информацию о действующем
placement.Middleware — это механизм, который позволяет добавлять логику обработки позиции, например, смещение, предотвращение выхода за границы экрана и автоматический флип.
offset(value) — задаёт смещение плавающего элемента от
привязки.flip() — меняет сторону, если исходная позиция выходит
за видимую область.shift(options) — корректирует позицию, чтобы элемент
полностью помещался в viewport.arrow({ element }) — позиционирует стрелку тултипа
относительно плавающего блока.Middleware можно комбинировать для сложных сценариев:
middleware: [
offset(10),
flip({ fallbackPlacements: ['bottom', 'right'] }),
shift({ padding: 8 }),
]
Floating UI поддерживает два типа стратегий:
absolute — позиционирование относительно ближайшего
ancestor с position: relative. Удобно для элементов внутри
контейнеров.fixed — позиционирование относительно viewport.
Используется, когда нужно избежать смещения при скролле.Пример:
computePosition(reference, floating, {
placement: 'bottom-start',
strategy: 'fixed',
});
Выбор стратегии влияет на поведение middleware: например,
shift будет работать по-разному для absolute и
fixed.
Floating UI предоставляет метод autoUpdate, который
автоматически отслеживает изменения в размерах и позициях reference или
floating элементов.
import { autoUpdate } from '@floating-ui/dom';
const cleanup = autoUpdate(reference, floating, () => {
computePosition(reference, floating, { placement: 'top' })
.then(({ x, y }) => Object.assign(floating.style, { left: `${x}px`, top: `${y}px` }));
});
// Для остановки наблюдения
cleanup();
Особенности:
Floating UI предоставляет DOM API и React API, которые отличаются по способу интеграции:
@floating-ui/react) —
использует хук useFloating, который возвращает координаты,
refs и удобные функции для middleware.Пример использования React API:
import { useFloating, offset, flip, shift } from '@floating-ui/react';
function Tooltip({ children }) {
const { x, y, reference, floating } = useFloating({
placement: 'top',
middleware: [offset(5), flip(), shift()],
});
return (
<>
<button ref={reference}>{children}</button>
<div ref={floating} style={{ position: 'absolute', top: y ?? 0, left: x ?? 0 }}>
Tooltip content
</div>
</>
);
}
Отличия:
computePosition и autoUpdate.Floating UI позволяет строить цепочки плавающих элементов, например,
контекстные меню с подменю. Используются комбинации
computePosition и middleware, чтобы каждый уровень меню
правильно флипался и не выходил за пределы экрана.
computePosition(parentMenuItem, subMenu, {
placement: 'right-start',
middleware: [offset(4), flip(), shift({ padding: 10 })],
});
Особенности:
Ранее для позиционирования часто использовались:
getBoundingClientRect() + ручная логика расчётаtransform и top/left с
привязкой к scrollFloating UI решает все эти проблемы через:
absolute и fixed, которые учитывают
контекст и скроллЭти различия делают Floating UI гибким инструментом для современных интерфейсов, позволяя сосредоточиться на логике приложения, а не на тонкостях расчёта позиций элементов.