Визуализация boundaries

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

При использовании Floating UI boundaries чаще всего управляются через опцию boundary в модуле computePosition или через middleware flip и shift.

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({ boundary: document.querySelector('#container') }),
    shift({ boundary: document.querySelector('#container') }),
  ],
});

В данном примере flip и shift используют boundaries для проверки, выйдет ли элемент за пределы контейнера #container.


Понимание типов boundaries

  1. Viewport Значение 'viewport' заставляет Floating UI ограничивать позицию элемента видимой областью экрана. Это стандартный вариант, когда нужно, чтобы тултип или меню всегда были полностью видимы пользователю.
flip({ boundary: 'viewport' });
shift({ boundary: 'viewport' });
  1. Clipping parent Опция 'clippingAncestors' или конкретный родительский элемент позволяет ограничивать плавающий элемент границами ближайшего контейнера с overflow, отличным от visible. Полезно для модальных окон и внутренних меню.
flip({ boundary: document.querySelector('.modal') });
shift({ boundary: document.querySelector('.modal') });
  1. Массив элементов Можно передать массив элементов, чтобы одновременно ограничивать позицию несколькими контейнерами. Floating UI будет учитывать все заданные границы и выбирать позицию, которая полностью помещает элемент.
shift({ boundary: [document.body, document.querySelector('.scrollable')] });

Middleware, управляющие boundaries

1. flip Отвечает за автоматическое изменение направления всплывающего элемента при достижении границы. Если тултип направлен вниз, но нет места, flip может перевернуть его вверх.

Параметры:

  • boundary: элемент или 'viewport'
  • padding: внутренние отступы от границы (по умолчанию 0)
  • fallbackPlacements: массив альтернативных позиций, которые будут проверяться при ограничении
flip({
  boundary: document.querySelector('#container'),
  padding: 8,
  fallbackPlacements: ['top', 'right', 'left'],
});

2. shift Используется для подстройки позиции, если элемент частично выходит за границы. В отличие от flip, не меняет направление, а лишь смещает элемент внутрь видимой области.

shift({ boundary: document.querySelector('#container'), padding: 5 });

3. autoPlacement Автоматически выбирает оптимальное место для элемента с учетом boundaries. Полезно для динамических интерфейсов с непредсказуемым расположением контейнеров.

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

computePosition(reference, floating, {
  middleware: [autoPlacement({ boundary: document.body, padding: 10 })],
});

Настройка padding и offset

  • padding задает внутренний отступ от границы, что предотвращает прилипание элемента к краям контейнера.
  • offset управляет расстоянием между reference-элементом и плавающим элементом, что вместе с boundaries позволяет создать аккуратное позиционирование.
computePosition(reference, floating, {
  middleware: [
    offset(12),
    shift({ boundary: document.body, padding: 10 }),
  ],
});

Сочетание нескольких boundaries

Можно комбинировать разные middleware и boundaries для точного контроля позиции:

computePosition(reference, floating, {
  middleware: [
    offset(8),
    flip({ boundary: document.body }),
    shift({ boundary: [document.body, document.querySelector('.scrollable')], padding: 5 }),
  ],
});

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


Практические рекомендации

  • Всегда указывать padding, чтобы элемент не прилипал к границам.
  • Для модальных окон использовать boundaries по ближайшему родителю с overflow, чтобы избежать “выпадения” за границы модалки.
  • Комбинировать flip и shift для плавного и предсказуемого поведения элементов.
  • Для динамических интерфейсов и адаптивного дизайна лучше использовать 'viewport' как основной boundary, добавляя специфические контейнеры при необходимости.

Если нужны примеры для React с использованием Floating UI React hooks, можно подробно разобрать, как boundaries влияют на useFloating и middleware внутри компонентов. Это позволяет интегрировать всплывающие элементы без ручного расчета позиции.