CSS подходы к оформлению

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

Ключевой момент: библиотека не занимается стилизацией элементов. Она возвращает координаты и размеры, оставляя полный контроль над внешним видом CSS.


Подходы к применению CSS

Абсолютное позиционирование

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

.tooltip {
  position: absolute;
  background-color: #333;
  color: #fff;
  padding: 6px 12px;
  border-radius: 4px;
  font-size: 14px;
  pointer-events: none;
  z-index: 1000;
}

Особенности:

  • pointer-events: none предотвращает блокировку событий мыши для элементов под тултипом.
  • z-index гарантирует нахождение элемента поверх других блоков.
  • Вычисленные координаты Floating UI применяются через top и left.
import { computePosition } from '@floating-ui/dom';

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

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

Управление трансформациями

Вместо прямого задания top и left можно использовать transform: translate() для плавного позиционирования. Такой подход особенно эффективен для анимаций.

.tooltip {
  transform: translate(0, 0);
  transition: transform 0.2s ease;
}
computePosition(reference, floating, {
  placement: 'bottom',
}).then(({ x, y }) => {
  floating.style.transform = `translate(${x}px, ${y}px)`;
});

Преимущество: элемент остаётся в потоке документа относительно родителя, что упрощает работу с overflow и анимациями.


Адаптация к viewport и ограничителям

Floating UI позволяет использовать модификаторы (middleware), такие как flip, shift и offset. Для корректного отображения важно учитывать CSS-свойства родителя:

  • overflow: hidden может обрезать плавающий элемент.
  • position: relative или absolute родителя влияет на систему координат.
import { flip, shift, offset } from '@floating-ui/dom';

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

CSS при этом остаётся стандартным: position: absolute и стили визуальной оболочки.


Стилизация направления и стрелок

Для создания стрелок (arrow) используется псевдоэлемент или отдельный div. Floating UI предоставляет координаты для стрелки, которые нужно применять через CSS.

.tooltip::after {
  content: '';
  position: absolute;
  width: 8px;
  height: 8px;
  background: #333;
  transform: rotate(45deg);
}
import { arrow } from '@floating-ui/dom';

const arrowEl = floating.querySelector('.tooltip-arrow');

computePosition(reference, floating, {
  placement: 'top',
  middleware: [arrow({ element: arrowEl })]
}).then(({ x, y, middlewareData }) => {
  Object.assign(floating.style, { left: `${x}px`, top: `${y}px` });
  const { x: arrowX, y: arrowY } = middlewareData.arrow;
  Object.assign(arrowEl.style, {
    left: arrowX != null ? `${arrowX}px` : '',
    top: arrowY != null ? `${arrowY}px` : ''
  });
});

Особенности CSS-оформления стрелки:

  • Размер и цвет настраиваются через стандартные свойства.
  • Поворот стрелки реализуется через transform: rotate(45deg).
  • Координаты рассчитываются Floating UI и подставляются напрямую в CSS.

Адаптивное позиционирование

Для элементов, которые должны динамически адаптироваться под изменения размера окна, важно сочетать CSS с middleware autoPlacement:

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

computePosition(reference, floating, {
  middleware: [autoPlacement()]
});

CSS остаётся прежним: position: absolute или transform, а библиотека автоматически корректирует top/left или translate.


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

Floating UI легко сочетается с Tailwind:

<div class="relative">
  <button id="button" class="px-4 py-2 bg-blue-500 text-white">Hover</button>
  <div class="tooltip bg-gray-800 text-white p-2 rounded absolute">Подсказка</div>
</div>

absolute используется для плавающего элемента, а Tailwind-классы управляют стилем. Позиционирование динамически подставляется через inline-стили, полученные от библиотеки.


Работа с темной и светлой темами

CSS-стили Floating UI не зависят от JavaScript. Для поддержки тем можно применять классы:

.tooltip {
  background-color: var(--tooltip-bg);
  color: var(--tooltip-text);
}
[data-theme="dark"] {
  --tooltip-bg: #333;
  --tooltip-text: #fff;
}
[data-theme="light"] {
  --tooltip-bg: #fff;
  --tooltip-text: #333;
}

JavaScript остаётся универсальным, меняются только CSS-переменные.


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

Использование CSS-переходов и transform делает анимацию плавной:

.tooltip {
  opacity: 0;
  transform: translateY(5px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.tooltip.show {
  opacity: 1;
  transform: translateY(0);
}

JavaScript управляет добавлением класса show после вычисления координат Floating UI, обеспечивая скоординированное отображение и анимацию.


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