FloatingArrow — это модуль в библиотеке Floating
UI, предназначенный для управления визуальным указателем
(стрелкой), который соединяет всплывающий элемент (popper, tooltip,
dropdown) с целевым элементом на странице. Он решает ключевую задачу:
обеспечить точное позиционирование стрелки независимо от
размеров и положения окна, сохраняя плавность адаптации при
динамических изменениях интерфейса.
Для работы со стрелкой необходимо импортировать модуль
arrow из @floating-ui/dom (для веб-приложений)
или @floating-ui/react-dom (для React):
import { computePosition, offset, flip, shift, arrow } from '@floating-ui/dom';
const reference = document.querySelector('#button');
const floating = document.querySelector('#tooltip');
const arrowElement = document.querySelector('#arrow');
computePosition(reference, floating, {
middleware: [
offset(10),
flip(),
shift({ padding: 5 }),
arrow({ element: arrowElement, padding: 5 }),
],
}).then(({ x, y, middlewareData }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`,
});
const { x: arrowX, y: arrowY } = middlewareData.arrow;
Object.assign(arrowElement.style, {
left: arrowX != null ? `${arrowX}px` : '',
top: arrowY != null ? `${arrowY}px` : '',
});
});
Ключевые моменты:
element — ссылка на DOM-элемент стрелки.padding — минимальное расстояние между стрелкой и
границами всплывающего элемента, предотвращающее её смещение за пределы
контейнера.middlewareData.arrow содержит координаты x
и y для точного позиционирования стрелки.element Обязательный параметр. Без
него стрелка не будет позиционироваться. Обычно это
<div> или <span> внутри
всплывающего контейнера.
padding Позволяет задать отступ
стрелки от краев всплывающего элемента. Удобно при округлых границах или
при необходимости оставить визуальный зазор.
axis Можно ограничить движение
стрелки по одной оси:
arrow({ element: arrowElement, axis: 'x' });
В этом случае стрелка будет смещаться только по горизонтали, что полезно для tooltip с фиксированной вертикальной позицией.
crossAxis Управляет смещением
стрелки перпендикулярно основной оси всплывающего элемента. Позволяет
избежать столкновений со скругленными краями или границами
контейнера.
FloatingArrow тесно интегрируется с другими middleware
Floating UI:
offset — задаёт расстояние между
reference и floating элементом.flip — обеспечивает автоматический
переворот всплывающего элемента при нехватке места. Стрелка при этом
корректно адаптируется.shift — предотвращает выход
всплывающего элемента за границы видимой области. Стрелка смещается
вместе с элементом.Важно помнить, что порядок middleware влияет на итоговое
позиционирование: arrow обычно идет последним, чтобы
координаты стрелки рассчитывались уже после смещения и переворота.
Когда всплывающий элемент реагирует на анимации, прокрутку или
изменение размеров, требуется обновлять позицию стрелки в
реальном времени. В Floating UI для этого используется функция
autoUpdate:
import { autoUpdate } from '@floating-ui/dom';
autoUpdate(reference, floating, () => {
computePosition(reference, floating, {
middleware: [offset(10), flip(), shift({ padding: 5 }), arrow({ element: arrowElement })],
}).then(({ x, y, middlewareData }) => {
Object.assign(floating.style, { left: `${x}px`, top: `${y}px` });
const { x: arrowX, y: arrowY } = middlewareData.arrow;
Object.assign(arrowElement.style, { left: arrowX != null ? `${arrowX}px` : '', top: arrowY != null ? `${arrowY}px` : '' });
});
});
Такое решение позволяет стрелке оставаться идеально выровненной даже при прокрутке страницы или изменении размеров окна.
Процентное смещение: Стрелку можно позиционировать в процентах относительно ширины или высоты всплывающего элемента. Это удобно для динамических контентных блоков.
CSS-перетекания: Можно использовать
transform: translate(-50%, -50%) для плавного
центрирования, особенно если стрелка имеет сложную форму или
декоративные эффекты.
Интерактивные элементы: В tooltip или dropdown стрелка может быть кликабельной или анимированной. FloatingArrow не ограничивает стилизацию — координаты остаются точными.
width, height) для корректного расчета.padding middleware arrow, если
есть скругленные края или декоративные рамки.axis и
crossAxis для предотвращения некорректного смещения.flip() —
особенно при ограниченной ширине окна.FloatingArrow превращает обычный tooltip или popper в
профессионально выверенный интерфейсный компонент,
обеспечивая согласованность позиционирования и плавность адаптации к
любым изменениям DOM.