Плавающие элементы и их назначение

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

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

  • Вычисление оптимальной позиции с учетом размеров и положения целевого элемента.
  • Учет границ окна просмотра (viewport) и контейнеров с ограничением видимости.
  • Автоматическое смещение при выходе за границы видимой области.
  • Поддержку различных стратегий позиционирования (например, absolute vs fixed).

Ядро библиотеки и основные функции

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

  1. computePosition — основная функция, вычисляющая координаты для плавающего элемента. Она принимает два аргумента: reference (элемент-оригинал) и floating (элемент-плавающий). Возвращает объект с координатами x и y и дополнительными сведениями о переполнении, смещениях и коллизиях.

  2. middleware — набор функций для модификации поведения позиционирования:

    • offset — задает смещение плавающего элемента относительно reference.
    • flip — автоматически меняет сторону размещения, если элемент выходит за границы видимой области.
    • shift — корректирует позицию, чтобы элемент оставался в пределах viewport.
    • arrow — вычисляет положение стрелки, если она используется в тултипах или дропдаунах.
  3. autoUpdate — функция, которая автоматически отслеживает изменения размеров и положения reference и floating элементов, пересчитывая координаты при скролле, ресайзе или изменении контента.

Позиционирование и стратегии

Floating UI поддерживает разные стратегии позиционирования:

  • absolute — элемент привязан к ближайшему предку с относительным позиционированием. Используется в стандартных контекстах документа.
  • fixed — элемент фиксирован относительно окна просмотра. Используется для тултипов и модальных окон, которые должны оставаться на экране при прокрутке страницы.

Выбор стратегии зависит от контекста: если элемент должен оставаться привязанным к reference при прокрутке родительского контейнера, используется absolute; если нужно независимое позиционирование на экране — fixed.

Middleware: детальная настройка поведения

Middleware позволяет гибко управлять поведением плавающих элементов:

  • Offset: задает смещение по осям X и Y, например, чтобы тултип не перекрывал reference.
import { offset } from '@floating-ui/dom';

const middleware = [offset(8)]; // смещение на 8 пикселей
  • Flip: меняет сторону размещения при выходе за границы viewport. Можно задавать приоритет сторон и предусматривать fallback позиции.
import { flip } from '@floating-ui/dom';

const middleware = [flip({ fallbackPlacements: ['top', 'left'] })];
  • Shift: корректирует координаты, если элемент частично выходит за границы видимой области.
import { shift } from '@floating-ui/dom';

const middleware = [shift({ padding: 5 })]; // оставляет 5px от края
  • Arrow: вычисляет положение стрелки для тултипов. Требует передать DOM-элемент стрелки и размеры.
import { arrow } from '@floating-ui/dom';

const middleware = [arrow({ element: arrowEl })];

Практические аспекты использования

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

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

autoUpdate(referenceEl, floatingEl, () => {
  computePosition(referenceEl, floatingEl, { middleware }).then(({ x, y }) => {
    Object.assign(floatingEl.style, { left: `${x}px`, top: `${y}px` });
  });
});

Контроль переполнения: Floating UI автоматически учитывает ограничения viewport и контейнеров с overflow: hidden/scroll. Middleware shift и flip помогают избежать ситуаций, когда элемент скрывается частично или полностью.

Комбинирование middleware: Можно объединять несколько middleware для комплексного поведения: например, сначала смещение, затем проверка переполнения и изменение стороны размещения, и затем вычисление позиции стрелки. Порядок middleware влияет на результат.

Взаимодействие с другими библиотеками

Floating UI легко интегрируется с React, Vue и другими фреймворками через специальные обертки и хуки. Для React используется пакет @floating-ui/react, где middleware и computePosition управляются через хук useFloating, упрощая синхронизацию с состоянием компонентов и ререндерингом интерфейса.

Ключевые преимущества

  • Полная контроль над позиционированием.
  • Адаптивность к изменениям DOM и viewport.
  • Минимальная зависимость от CSS.
  • Модульность и расширяемость через middleware.
  • Универсальность для тултипов, дропдаунов, модальных окон и всплывающих меню.

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