Контекстное меню — это элемент интерфейса, который появляется при взаимодействии с пользователем, чаще всего при клике правой кнопкой мыши. В библиотеке Floating UI управление позиционированием таких элементов становится гибким и точным.
Floating UI предоставляет низкоуровневые функции для вычисления
позиции всплывающих элементов относительно их якорей. Основной
инструмент — функция computePosition, которая принимает два
обязательных аргумента:
reference — элемент, относительно которого будет
позиционироваться меню.floating — само всплывающее меню.Простейший пример:
import { computePosition, offset, flip, shift } from '@floating-ui/dom';
const reference = document.querySelector('#target');
const floating = document.querySelector('#context-menu');
reference.addEventListener('contextmenu', async (event) => {
event.preventDefault();
const { x, y } = await computePosition(reference, floating, {
middleware: [
offset(4), // отступ от якоря
flip(), // автоматический переворот, если меню не помещается
shift() // корректировка позиции при выходе за границы окна
],
});
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`,
position: 'absolute',
display: 'block'
});
});
Ключевые моменты:
offset добавляет смещение от якоря,
чтобы меню не накладывалось на элемент.flip обеспечивает видимость меню при
нехватке места с одной стороны.shift предотвращает выход меню за
границы окна.Для контекстного меню часто нужно открытие не строго относительно DOM-элемента, а в точке клика. Floating UI позволяет использовать координаты события мыши как «виртуальный элемент»:
const virtualReference = {
getBoundingClientRect: () => ({
x: event.clientX,
y: event.clientY,
width: 0,
height: 0,
top: event.clientY,
left: event.clientX,
right: event.clientX,
bottom: event.clientY
}),
contextElement: reference
};
Далее virtualReference передается в
computePosition вместо реального DOM-узла:
const { x, y } = await computePosition(virtualReference, floating, {
middleware: [offset(4), flip(), shift()]
});
Такое решение идеально для кастомных контекстных меню, появляющихся по клику правой кнопкой в любой точке интерфейса.
Floating UI предоставляет возможность динамически изменять позицию при скролле или изменении размеров окна:
import { autoUpdate } from '@floating-ui/dom';
autoUpdate(reference, floating, () => {
computePosition(reference, floating, {
middleware: [offset(4), flip(), shift()]
}).then(({ x, y }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`
});
});
});
autoUpdate следит за изменениями и
автоматически пересчитывает позицию.Middleware — это мощный инструмент для кастомизации поведения всплывающих элементов:
Пример использования стрелки:
import { arrow } from '@floating-ui/dom';
const arrowElement = document.querySelector('.arrow');
computePosition(reference, floating, {
middleware: [offset(8), flip(), shift(), arrow({ element: arrowElement })]
}).then(({ x, y, middlewareData }) => {
const { x: arrowX, y: arrowY } = middlewareData.arrow;
Object.assign(arrowElement.style, {
left: arrowX != null ? `${arrowX}px` : '',
top: arrowY != null ? `${arrowY}px` : ''
});
Object.assign(floating.style, { left: `${x}px`, top: `${y}px` });
});
Стрелка автоматически выравнивается относительно меню и его якоря, делая интерфейс интуитивным.
Floating UI не отвечает за анимацию, но легко интегрируется с CSS-переходами:
.context-menu {
transition: opacity 0.2s ease, transform 0.2s ease;
opacity: 0;
transform: scale(0.95);
}
.context-menu.show {
opacity: 1;
transform: scale(1);
}
В Jav * aScript:
floating.classList.add('show'); // появляется с анимацией
floating.classList.remove('show'); // скрытие с анимацией
Сочетание точного позиционирования Floating UI и плавной анимации CSS обеспечивает современное ощущение интерфейса.
Меню должно закрываться при клике вне или при выборе пункта:
document.addEventListener('click', (event) => {
if (!floating.contains(event.target)) {
floating.style.display = 'none';
}
});
Также можно закрывать меню при скролле или изменении размеров окна,
используя ту же функцию autoUpdate с обратным вызовом для
скрытия.
Комбинируя все описанные техники:
Floating UI становится полноценным инструментом для создания контекстного меню, полностью управляемого с точки зрения позиции и поведения, без привязки к конкретным UI-фреймворкам.