useFloating — это хук из библиотеки Floating UI,
предназначенный для динамического позиционирования всплывающих элементов
относительно якоря. В контексте Vue он позволяет легко интегрировать
всплывающие панели, тултипы, меню и модальные окна, сохраняя правильное
позиционирование при изменении размеров экрана или прокрутке.
Для начала нужно подключить хук и необходимые вспомогательные функции:
import { useFloating, offset, flip, shift, autoUpdate } from '@floating-ui/vue';
import { ref } from 'vue';
Создание реактивных ссылок на элементы якоря и всплывающего блока:
const reference = ref(null); // элемент, относительно которого позиционируется
const floating = ref(null); // всплывающий элемент
Инициализация useFloating с базовыми настройками:
const { x, y, strategy, update, middlewareData } = useFloating(reference, floating, {
placement: 'bottom-start',
middleware: [offset(8), flip(), shift()],
whileElementsMounted: autoUpdate
});
Ключевые параметры:
placement — начальное положение всплывающего элемента
(например, top, bottom-start).middleware — массив функций для обработки
позиционирования (offset, flip,
shift и другие).whileElementsMounted — функция для автоматического
обновления позиции при изменении DOM или скролла.Middleware позволяют управлять поведением всплывающего элемента:
offset(value) — задаёт смещение относительно якоря,
может быть числом или функцией.flip() — автоматически переворачивает всплывающее окно
при недостатке места.shift() — смещает элемент, чтобы он не выходил за
границы видимой области.arrow({ element }) — выравнивает стрелку всплывающего
блока к якорю.size() — динамически меняет размер всплывающего
элемента в зависимости от доступного пространства.Пример с использованием стрелки:
import { arrow } from '@floating-ui/vue';
const arrowRef = ref(null);
const { x, y, middlewareData } = useFloating(reference, floating, {
placement: 'top',
middleware: [offset(10), flip(), shift(), arrow({ element: arrowRef })]
});
x и y — это реактивные значения, которые
напрямую привязываются к стилям всплывающего элемента:
<template>
<div ref="reference">Кнопка</div>
<div ref="floating" :style="{ position: strategy, top: `${y}px`, left: `${x}px` }">
Всплывающее окно
<div ref="arrowRef" class="arrow"></div>
</div>
</template>
strategy обычно принимает значения absolute
или fixed, влияя на контекст позиционирования.
Использование autoUpdate обеспечивает автоматическое
пересчитывание координат при скролле, изменении размеров окна или
элемента.
Иногда требуется вручную обновлять позицию, например, после анимации или динамического изменения контента:
const handleResize = () => {
update(); // пересчёт позиции
};
window.addEventListener('resize', handleResize);
Можно комбинировать useFloating с событиями Vue для
управления видимостью всплывающих элементов:
<template>
<button ref="reference" @mouseenter="open = true" @mouseleave="open = false">
Навести
</button>
<div v-if="open" ref="floating" :style="{ position: strategy, top: `${y}px`, left: `${x}px` }">
Тултип
</div>
</template>
<script setup>
import { ref } from 'vue';
import { useFloating, offset, flip, shift, autoUpdate } from '@floating-ui/vue';
const reference = ref(null);
const floating = ref(null);
const open = ref(false);
const { x, y, strategy } = useFloating(reference, floating, {
placement: 'top',
middleware: [offset(5), flip(), shift()],
whileElementsMounted: autoUpdate
});
</script>
useFloating поддерживает комбинированное использование
нескольких middleware и динамическое изменение placement в
зависимости от состояния:
placement на лету.shift и flip всплывающий элемент
остаётся видимым на небольших экранах.x и
y можно использовать с CSS-переходами или Vue Transition
для плавного появления.autoUpdate только при активном всплывающем
элементе.useFloating в Vue предоставляет гибкий и мощный
инструмент для реализации адаптивных всплывающих интерфейсов, позволяя
контролировать позиционирование, динамически реагировать на изменения и
интегрироваться с реактивной системой Vue.