Что такое Floating UI

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

Главная задача Floating UI — отделить логику позиционирования от визуального отображения, предоставляя программисту мощный API для управления позиционированием.


Основные принципы работы

1. Элементы: Reference и Floating

В Floating UI выделяются два ключевых элемента:

  • Reference — элемент, относительно которого позиционируется всплывающий блок. Например, кнопка, при наведении на которую появляется подсказка.
  • Floating — сам всплывающий элемент, который необходимо разместить. Это может быть тултип, меню или кастомный компонент.

Эти два элемента связываются через позиционирующий механизм, который вычисляет оптимальные координаты.


2. Positioning API

Floating UI предоставляет функции для вычисления позиции:

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

computePosition(referenceElement, floatingElement, {
  placement: 'bottom-start',
  middleware: [
    offset(10),
    flip(),
    shift({ padding: 5 })
  ]
}).then(({ x, y }) => {
  Object.assign(floatingElement.style, {
    left: `${x}px`,
    top: `${y}px`
  });
});
  • placement — определяет предпочтительное расположение (top, bottom, left, right и их вариации).

  • middleware — набор функций, которые изменяют поведение позиционирования:

    • offset — смещение от reference;
    • flip — позволяет элементу переворачиваться, если не помещается;
    • shift — корректирует позицию для предотвращения выхода за пределы видимой области.

3. Middleware: гибкая настройка поведения

Middleware — ключевая особенность Floating UI. Каждая функция middleware принимает исходные координаты и возвращает новые. Примеры:

  • flip() Перемещает floating элемент на противоположную сторону, если исходное место не помещается в viewport.

  • shift({ padding }) Сдвигает элемент внутрь видимой области с заданным отступом.

  • size() Автоматически подстраивает размеры floating элемента под доступное пространство.

  • arrow({ element }) Создает динамическую стрелку, указывающую на reference элемент.

Middleware можно комбинировать для сложных сценариев:

middleware: [
  offset(8),
  flip(),
  shift({ padding: 5 }),
  arrow({ element: arrowElement })
]

Реактивное позиционирование

Floating UI поддерживает обновление позиции в режиме реального времени при изменении размеров окна, скролле или изменении содержимого:

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

const cleanup = autoUpdate(referenceElement, floatingElement, () => {
  computePosition(referenceElement, floatingElement, { placement: 'bottom' })
    .then(({ x, y }) => {
      Object.assign(floatingElement.style, { left: `${x}px`, top: `${y}px` });
    });
});

// Для остановки отслеживания изменений
cleanup();

autoUpdate следит за всеми необходимыми событиями и автоматически пересчитывает координаты, обеспечивая корректное поведение при динамическом изменении интерфейса.


Управление видимостью

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

referenceElement.addEventListener('mouseenter', () => {
  floatingElement.style.display = 'block';
  computePosition(referenceElement, floatingElement, { placement: 'top' });
});

referenceElement.addEventListener('mouseleave', () => {
  floatingElement.style.display = 'none';
});

Поддержка различных платформ

Библиотека разделена на два основных пакета:

  • @floating-ui/dom — для работы с DOM в браузере.
  • @floating-ui/react — адаптация для React с хуками и компонентами.

В React можно использовать хук useFloating:

import { useFloating, offset, flip } from '@floating-ui/react';

const { x, y, reference, floating } = useFloating({
  placement: 'bottom',
  middleware: [offset(10), flip()]
});

reference и floating используются как ref для элементов React, обеспечивая автоматическое позиционирование без ручного доступа к DOM.


Особенности, повышающие гибкость

  • Композиция middleware позволяет создавать сложные цепочки логики позиционирования.
  • Интеграция с анимациями возможна через прямое управление стилями.
  • Обработка ограничений viewport обеспечивает удобство при адаптивном дизайне.
  • Поддержка виртуальных элементов позволяет позиционировать floating элементы относительно абстрактных точек или координат, а не только DOM-элементов.

Примеры практического применения

  1. Тултипы: всплывающая подсказка при наведении.
  2. Dropdown-меню: автоматическое открытие в пределах окна.
  3. Контекстные меню: позиционирование по курсору мыши.
  4. Модальные элементы с динамическим смещением: адаптивное позиционирование в сложных интерфейсах.

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