Floating UI — это библиотека для создания плавающих элементов интерфейса, таких как тултипы, поповеры, дропдауны и модальные окна, с точным управлением позиционированием относительно целевых элементов. В основе работы лежит понятие reference element (элемент, относительно которого позиционируется плавающий блок) и floating element (сам плавающий блок).
Reference элемент — это DOM-узел, вокруг которого строится логика позиционирования. Floating элемент может быть абсолютно позиционированным элементом, который следует за reference элементом, учитывая ограничения контейнера, viewport и другие условия.
import { computePosition } from '@floating-ui/dom';
const reference = document.querySelector('#button');
const floating = document.querySelector('#tooltip');
computePosition(reference, floating, {
placement: 'top',
}).then(({ x, y }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`,
});
});
Placement — ключевой параметр, определяющий
расположение floating элемента относительно reference. В Floating UI
используется формат "side-alignment":
top, bottom, left,
right — стороны относительно reference.top-start, top-end,
bottom-start, bottom-end — уточненные позиции
с учетом выравнивания по краям.Middleware — цепочка функций, которые изменяют позицию плавающего элемента перед её окончательной установкой. Основные middleware:
Пример использования middleware:
import { offset, flip, shift, arrow } from '@floating-ui/dom';
computePosition(reference, floating, {
placement: 'bottom',
middleware: [
offset(8),
flip(),
shift({ padding: 5 }),
arrow({ element: document.querySelector('#arrow') }),
],
}).then(({ x, y, middlewareData }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`,
});
const { x: arrowX, y: arrowY } = middlewareData.arrow;
Object.assign(document.querySelector('#arrow').style, {
left: arrowX != null ? `${arrowX}px` : '',
top: arrowY != null ? `${arrowY}px` : '',
});
});
Floating UI позволяет отслеживать изменения размера reference и
viewport, чтобы динамически обновлять позицию floating элемента. Для
этого используется метод autoUpdate:
import { autoUpdate } from '@floating-ui/dom';
const cleanup = autoUpdate(reference, floating, () => {
computePosition(reference, floating, {
placement: 'top',
middleware: [offset(10), flip(), shift()],
}).then(({ x, y }) => {
Object.assign(floating.style, { left: `${x}px`, top: `${y}px` });
});
});
autoUpdate автоматически реагирует на:
Возвращаемая функция cleanup позволяет остановить
наблюдение.
Для стрелок используется middleware arrow, которое
принимает DOM-узел стрелки и вычисляет её координаты:
flip и shift.arrow({ element: arrowEl, padding: 5 });
padding задаёт минимальное расстояние стрелки от краёв
floating элемента.
Middleware shift и flip учитывают
ограничения контейнера или viewport. Можно задать:
boundary — элемент, в пределах которого элемент не
должен выходить.padding — минимальное расстояние от границ
контейнера.shift({ boundary: document.querySelector('#container'), padding: 10 });
const virtualReference = {
getBoundingClientRect: () => ({
x: mouseX,
y: mouseY,
width: 0,
height: 0,
top: mouseY,
bottom: mouseY,
left: mouseX,
right: mouseX,
}),
};
computePosition(virtualReference, floating, {
placement: 'right',
middleware: [offset(5)],
});
Floating UI предоставляет обёртки для React
(@floating-ui/react) и других библиотек, упрощая
использование через хуки:
import { useFloating, offset, flip, shift } from '@floating-ui/react';
const { x, y, reference, floating } = useFloating({
placement: 'bottom',
middleware: [offset(10), flip(), shift()],
});
reference и floating — рефы, привязанные к
DOM элементам.x и y — координаты, автоматически
обновляемые при изменениях размеров и скролла.Эта архитектура позволяет строить полностью реактивные и управляемые плавающие интерфейсы без ручного отслеживания событий и пересчётов.
flip, shift и offset для
устойчивого поведения в любых условиях.Floating UI предоставляет тонкий контроль над позиционированием и адаптивностью интерфейса, делая его идеальным инструментом для создания динамических, интерактивных элементов в современных веб-приложениях.