Интеграция с CSS

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

Управление положением через CSS-переменные

Floating UI позволяет вычислять координаты x и y для всплывающего элемента. Для интеграции с CSS удобно использовать CSS-переменные:

import { computePosition, offset, flip, shift } from '@floating-ui/dom';

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

computePosition(reference, floating, {
  middleware: [offset(10), flip(), shift({ padding: 5 })],
}).then(({ x, y }) => {
  floating.style.setProperty('--floating-x', `${x}px`);
  floating.style.setProperty('--floating-y', `${y}px`);
});
#tooltip {
  position: absolute;
  left: var(--floating-x);
  top: var(--floating-y);
  transition: transform 0.2s ease, opacity 0.2s ease;
}

Ключевые моменты:

  • Использование CSS-переменных позволяет применять динамическое позиционирование с плавными анимациями через transform.
  • Переход от прямого left/top к transform: translate() повышает производительность на крупных страницах и минимизирует «пересчёт компоновки» (reflow).

Позиционирование с transform: translate()

Floating UI рекомендует использовать transform: translate() для отображения элементов, чтобы избежать проблем с layout. Это реализуется следующим образом:

computePosition(reference, floating, {
  middleware: [offset(8), flip(), shift()],
}).then(({ x, y }) => {
  floating.style.transform = `translate(${x}px, ${y}px)`;
});
#tooltip {
  position: absolute;
  will-change: transform;
}

Пояснение:

  • will-change: transform сообщает браузеру о будущих изменениях, что позволяет заранее оптимизировать рендеринг.
  • Использование transform вместо left/top уменьшает дергание при анимации и улучшает плавность.

Middleware и CSS-эффекты

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

  1. offset – добавляет смещение относительно reference-элемента. CSS-анимации могут учитывать смещение для плавного «выдвижения» элемента.
  2. flip – автоматически меняет позицию при выходе за пределы viewport. Можно использовать CSS-трансформации для эффекта «переворачивания» тултипа.
  3. shift – корректирует положение при перекрытии границ контейнера. Комбинируется с CSS-переходами для мягкой корректировки позиции.
middleware: [
  offset({ mainAxis: 10 }),
  flip(),
  shift({ padding: 5 }),
]
#tooltip {
  transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

Анимации появления и исчезновения

Для плавного отображения элементов Floating UI часто используют opacity и scale в сочетании с transform:

#tooltip {
  opacity: 0;
  transform: scale(0.95) translate(var(--floating-x), var(--floating-y));
  transition: opacity 0.2s ease, transform 0.2s ease;
}

#tooltip[data-show] {
  opacity: 1;
  transform: scale(1) translate(var(--floating-x), var(--floating-y));
}
reference.addEventListener('mouseenter', () => {
  floating.setAttribute('data-show', '');
  computePosition(reference, floating, { middleware: [offset(8), flip(), shift()] })
    .then(({ x, y }) => {
      floating.style.setProperty('--floating-x', `${x}px`);
      floating.style.setProperty('--floating-y', `${y}px`);
    });
});

reference.addEventListener('mouseleave', () => {
  floating.removeAttribute('data-show');
});

Важные моменты:

  • scale создаёт эффект «выезжания» элемента.
  • Синхронизация transform и переменных позволяет одновременно корректировать позицию и анимацию.

Работа с адаптивным дизайном

Floating UI легко интегрируется с CSS-медиа-запросами и переменными для адаптивного позиционирования:

@media (max-width: 768px) {
  #tooltip {
    font-size: 14px;
    padding: 6px 10px;
  }
}
computePosition(reference, floating, {
  strategy: window.innerWidth < 768 ? 'fixed' : 'absolute',
  middleware: [offset(6), flip(), shift()],
});
  • strategy: fixed предотвращает сдвиги при прокрутке на мобильных устройствах.
  • Комбинация с медиа-запросами позволяет менять размеры, padding и позицию без переписывания JS-логики.

Использование CSS-псевдоклассов и data-атрибутов

Floating UI отлично работает с data-* атрибутами для состояния видимости, что упрощает интеграцию с CSS-псевдоклассами:

#tooltip[data-placement^="top"]::after {
  content: "";
  position: absolute;
  bottom: -6px;
  left: 50%;
  transform: translateX(-50%);
  border-width: 6px 6px 0 6px;
  border-style: solid;
  border-color: #333 transparent transparent transparent;
}
computePosition(reference, floating, { middleware: [offset(8), flip(), shift()] })
  .then(({ x, y, placement }) => {
    floating.setAttribute('data-placement', placement);
    floating.style.setProperty('--floating-x', `${x}px`);
    floating.style.setProperty('--floating-y', `${y}px`);
  });
  • data-placement позволяет реализовать динамические стрелки, подсказки и разные визуальные варианты.
  • CSS остаётся полностью декларативным, а JS управляет только вычислениями позиции.

Комбинирование с CSS Grid и Flexbox

Floating UI не ограничен абсолютным позиционированием — его можно сочетать с современными layout-методами:

.popup-container {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  position: relative;
}

#tooltip {
  position: absolute;
}
  • Элемент reference может находиться внутри flex-контейнера, при этом Floating UI корректно вычисляет координаты с учётом всех родительских трансформаций.
  • position: relative на контейнере гарантирует правильное смещение относительно родителя.

Эти методы позволяют создавать высокопроизводительные, визуально плавные всплывающие элементы с полной поддержкой CSS-стилей, адаптивности и анимаций, максимально используя возможности Floating UI.