Референсный элемент

Референсный элемент в Floating UI — это точка привязки, относительно которой позиционируется плавающее окно (floating element). Его можно рассматривать как якорь: все расчёты положения всплывающих элементов (tooltip, dropdown, popover и др.) строятся относительно него. Референсный элемент может быть любым DOM-узлом, включая <div>, <button> или даже виртуальные элементы, которые не отображаются на странице, но имеют координаты.

Ключевой особенностью Floating UI является отделение вычислений позиции от рендеринга, что позволяет гибко управлять поведением элементов без прямой привязки к CSS.


Использование референсного элемента

Получение позиции

Floating UI использует функцию computePosition, которая принимает референсный элемент и плавающий элемент, а возвращает объект с координатами:

import { computePosition } from '@floating-ui/dom';

const reference = document.querySelector('#button');
const floating = document.querySelector('#tooltip');

computePosition(reference, floating).then(({ x, y }) => {
  Object.assign(floating.style, {
    left: `${x}px`,
    top: `${y}px`
  });
});
  • reference — DOM-узел, вокруг которого будет позиционироваться плавающее окно.
  • floating — элемент, который необходимо позиционировать.
  • x, y — рассчитанные координаты с учётом всех модификаторов и сдвигов.

Виртуальные референсы

Floating UI поддерживает виртуальные референсы, которые полезны, когда позицию нужно вычислить на основе мыши, курсора или динамических координат:

const virtualReference = {
  getBoundingClientRect: () => ({
    x: 100,
    y: 150,
    width: 0,
    height: 0,
    top: 150,
    right: 100,
    bottom: 150,
    left: 100,
  }),
  contextElement: document.body
};

computePosition(virtualReference, floating).then(({ x, y }) => {
  floating.style.left = `${x}px`;
  floating.style.top = `${y}px`;
});

Такой подход особенно удобен для всплывающих подсказок при наведении мыши или кастомных элементов интерфейса без реального DOM-узла.


Взаимодействие с модификаторами

Референсный элемент работает в связке с middleware (модификаторами), которые корректируют позицию плавающего окна. Основные middleware:

  • offset — добавляет отступ между референсом и плавающим элементом:
import { offset } from '@floating-ui/dom';

computePosition(reference, floating, {
  middleware: [offset(10)]
});
  • flip — автоматически меняет сторону, если всплывающее окно выходит за границы видимой области.
  • shift — корректирует положение, чтобы элемент не выходил за границы окна.
  • arrow — позиционирует стрелку относительно референса.

Middleware используют информацию о bounding rect референсного элемента, что делает расчёты точными и гибкими.


Обновление позиции

Референсный элемент может быть динамическим, поэтому Floating UI предлагает функции обновления позиции в реальном времени. Два подхода:

  1. Периодическое вычисление:
function update() {
  computePosition(reference, floating).then(({ x, y }) => {
    Object.assign(floating.style, { left: `${x}px`, top: `${y}px` });
  });
  requestAnimationFrame(update);
}

update();
  1. Событийный подход с autoUpdate:
import { autoUpdate } from '@floating-ui/dom';

const cleanup = autoUpdate(reference, floating, () => {
  computePosition(reference, floating).then(({ x, y }) => {
    Object.assign(floating.style, { left: `${x}px`, top: `${y}px` });
  });
});

// для остановки наблюдения
cleanup();

autoUpdate автоматически отслеживает изменения положения или размера референсного элемента и обновляет координаты плавающего элемента.


Особенности и ограничения

  • Невидимые элементы: если референс скрыт (display: none), getBoundingClientRect вернёт нулевые значения. Для скрытых элементов нужно использовать виртуальные референсы.
  • Прокрутка и трансформации: координаты рассчитываются относительно viewport, поэтому наличие трансформов на родительских элементах может повлиять на позицию.
  • Производительность: частые вызовы computePosition при скролле или ресайзе могут быть затратными; рекомендуется использовать autoUpdate с оптимизацией или throttling.

Практические сценарии

  1. Tooltip над кнопкой — классический случай использования референса для позиционирования с offset и flip.
  2. Контекстное меню у курсора — виртуальный референс заменяет реальный DOM-узел.
  3. Popovers с динамическим содержимым — autoUpdate позволяет корректировать позицию при изменении размеров содержимого.
  4. Комбинации с arrow middleware — точное позиционирование стрелки относительно якоря.

Референсный элемент — ядро позиционирования в Floating UI. Правильное использование DOM-узлов или виртуальных объектов обеспечивает точные, адаптивные и гибкие всплывающие интерфейсы.