Web Animations API

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


Установка и импорт

Для использования Floating UI достаточно установить пакет через npm или yarn:

npm install @floating-ui/dom

Импорт базовых функций осуществляется следующим образом:

import { computePosition, offset, flip, shift, arrow } from '@floating-ui/dom';
  • computePosition — вычисляет координаты всплывающего элемента относительно целевого.
  • offset — добавляет смещение между элементами.
  • flip — автоматически меняет позицию, если всплывающий элемент выходит за границы окна.
  • shift — корректирует положение элемента, чтобы он не выходил за пределы viewport.
  • arrow — управляет положением стрелки для тултипов и поповеров.

Вычисление позиции

Ключевой функцией является computePosition. Она принимает два основных параметра: целевой элемент (reference) и всплывающий элемент (floating), а также объект с опциями, содержащий список модификаторов.

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

computePosition(reference, floating, {
  placement: 'top',
  middleware: [offset(10), flip(), shift({ padding: 5 })]
}).then(({ x, y }) => {
  Object.assign(floating.style, {
    left: `${x}px`,
    top: `${y}px`
  });
});
  • placement — определяет начальное направление всплывающего элемента: top, bottom, left, right, а также варианты с -start и -end.
  • middleware — массив функций, которые модифицируют или корректируют позицию.

Модификаторы применяются последовательно, что позволяет строить сложные сценарии позиционирования.


Модификаторы

offset

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

offset(12) // фиксированное смещение 12px

flip

Меняет позицию всплывающего элемента, если он выходит за пределы видимой области окна. Работает в паре с placement.

flip({
  fallbackPlacements: ['bottom', 'left', 'right']
});

shift

Подгоняет элемент так, чтобы он оставался внутри viewport, предотвращая обрезку.

shift({ padding: 8 });

arrow

Используется для позиционирования стрелки тултипа или поповера. Требует передачи DOM-элемента стрелки.

arrow({ element: document.querySelector('#arrow') });

Асинхронное обновление позиции

Floating UI поддерживает динамическое позиционирование при изменении размеров окна или содержимого. Для этого используют autoUpdate.

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

const cleanup = autoUpdate(reference, floating, () => {
  computePosition(reference, floating, {
    placement: 'top',
    middleware: [offset(10), flip(), shift()]
  }).then(({ x, y }) => {
    Object.assign(floating.style, { left: `${x}px`, top: `${y}px` });
  });
});

// Для остановки автоматического обновления
cleanup();

autoUpdate отслеживает события resize, scroll и изменение DOM, обеспечивая корректное позиционирование в реальном времени.


Использование с анимациями

Для плавного появления и скрытия элементов часто применяют CSS-переходы или Web Animations API. Пример с Web Animations API:

floating.animate([
  { opacity: 0, transform: 'translateY(-5px)' },
  { opacity: 1, transform: 'translateY(0)' }
], {
  duration: 200,
  easing: 'ease-out'
});

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


Поддержка нескольких всплывающих элементов

Для сложных интерфейсов можно управлять несколькими тултипами или поповерами одновременно:

const buttons = document.querySelectorAll('.btn');

buttons.forEach(btn => {
  const tooltip = btn.querySelector('.tooltip');
  autoUpdate(btn, tooltip, () => {
    computePosition(btn, tooltip, {
      placement: 'top',
      middleware: [offset(8), flip(), shift()]
    }).then(({ x, y }) => {
      Object.assign(tooltip.style, { left: `${x}px`, top: `${y}px` });
    });
  });
});

Такой подход минимизирует код и упрощает поддержку интерфейсов с большим количеством динамических элементов.


Интеграция с фреймворками

Floating UI легко интегрируется с React, Vue и Svelte, предоставляя удобные хуки или компоненты-обертки. Основная концепция не меняется: вычисление позиции, применение модификаторов и управление отображением через стиль или классы.


Особенности и рекомендации

  • Всегда указывать middleware, даже если нужен только offset, чтобы обеспечить расширяемость.
  • Использовать autoUpdate для элементов, которые могут смещаться при прокрутке или изменении DOM.
  • При работе с стрелками (arrow) учитывать их размеры в offset и shift, чтобы элемент не перекрывал границы контейнера.
  • Комбинировать Floating UI с Web Animations API для создания современных, плавных интерфейсов.

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