Библиотека Floating UI предоставляет мощные инструменты для управления позиционированием всплывающих элементов (popper, tooltip, dropdown и других). Одним из ключевых аспектов точного позиционирования является смещение по осям, которое позволяет контролировать расстояние между целевым элементом и плавающим элементом, а также корректировать положение с учётом особенностей интерфейса.
offsetВ Floating UI смещение задаётся через модуль offset,
который принимает параметры для регулировки позиции по горизонтали и
вертикали.
import { offset } from '@floating-ui/dom';
const middleware = [offset({ mainAxis: 10, crossAxis: 5 })];
Пояснение параметров:
mainAxis — смещение вдоль основной оси позиции. Если
элемент позиционируется сверху (top), основная ось —
вертикальная, и положительное значение будет отодвигать элемент вниз.
Для позиции left основная ось — горизонтальная.crossAxis — смещение вдоль перекрёстной оси
(перпендикулярной основной). Это полезно, когда нужно сдвинуть элемент
вправо или влево относительно центра целевого элемента.alignmentAxis — используется для уточнения смещения при
центрированной позиции (например, start или
end).offset может принимать не только фиксированные числа, но
и функцию, возвращающую значения на основе размеров элементов:
offset(({ rects, placement }) => {
if (placement.startsWith('top')) {
return { mainAxis: rects.reference.height + 8, crossAxis: 0 };
}
return { mainAxis: 10, crossAxis: 5 };
});
Пояснение:
rects.reference — размеры и положение целевого
элемента.rects.floating — размеры плавающего элемента.placement — текущее позиционирование (например,
top-start, bottom-end), позволяющее менять
смещение в зависимости от направления.Такой подход обеспечивает адаптивность интерфейса: всплывающий элемент корректно располагается даже при изменении размера окна или контента.
Смещение часто используется вместе с flip и
shift для предотвращения выхода элемента за границы
окна:
import { computePosition, offset, flip, shift } from '@floating-ui/dom';
computePosition(reference, floating, {
middleware: [
offset({ mainAxis: 12, crossAxis: 0 }),
flip({ fallbackPlacements: ['bottom', 'right'] }),
shift({ padding: 5 })
],
});
flip — изменяет позицию, если плавающий элемент не
помещается на текущей оси.shift — корректирует смещение, чтобы элемент не выходил
за пределы видимой области.Важно: offset применяется
до flip и shift, поэтому
значения смещения учитываются при вычислении возможных альтернативных
позиций.
При использовании контейнеров с прокруткой или CSS-трансформациями, смещение по осям остаётся точным, если вычислять позицию через Floating UI DOM API:
computePosition(reference, floating, {
strategy: 'fixed',
middleware: [offset({ mainAxis: 15 })],
});
strategy: 'fixed' — игнорирует скролл страницы и
фиксирует элемент относительно окна.strategy: 'absolute' — смещение рассчитывается
относительно ближайшего позиционированного родителя.Это особенно полезно для модальных окон, тултипов внутри
скроллируемых контейнеров и элементов с CSS transform.
rects) для вычисления смещения.top,
bottom, left, right), смещение
должно корректно работать для всех.computePosition(reference, floating, {
placement: 'top-start',
middleware: [
offset(({ rects }) => {
const spacing = rects.reference.height * 0.2;
return { mainAxis: spacing, crossAxis: 10 };
}),
flip(),
shift({ padding: 8 })
],
});
В этом примере смещение рассчитывается динамически, адаптируясь под размеры целевого элемента, а flip и shift обеспечивают корректное отображение при ограниченном пространстве.