Boundary constraints

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

Понятие границ

Граница (boundary) — это элемент DOM или область экрана, внутри которой всплывающий элемент должен оставаться видимым. Она используется вместе с модификатором flip или preventOverflow, чтобы предотвращать выход всплывающих панелей за пределы допустимой области.

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

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

computePosition(reference, floating, {
  middleware: [
    offset(8),
    flip(),
    shift({ limiter: limitShift({ boundary: document.body }) })
  ],
}).then(({ x, y }) => {
  Object.assign(floating.style, {
    left: `${x}px`,
    top: `${y}px`
  });
});

В этом примере:

  • offset(8) задаёт отступ от якоря.
  • flip() позволяет элементу автоматически изменять направление при нехватке места.
  • shift() корректирует позицию так, чтобы элемент оставался в пределах границы.
  • limitShift({ boundary }) указывает конкретную границу, за которую элемент не должен выходить.

Использование ограничений

Ограничения границ могут применяться к различным типам элементов:

  1. Вьюпорт (viewport) — элемент не выходит за видимую область окна браузера.
  2. Элемент-контейнер — элемент остаётся внутри родительского контейнера или определённого блока.
  3. Произвольная область — можно задать кастомный DOM-элемент в качестве границы.
shift({
  limiter: limitShift({ boundary: document.querySelector('#container') })
})

Здесь всплывающий элемент будет оставаться внутри контейнера с id container.

Настройка поведения при достижении границ

Опции shift и limitShift позволяют управлять поведением при ограничении пространства:

  • padding — внутренний отступ между элементом и границей.
  • mainAxis — корректировка по основной оси (например, вертикальной для top/bottom).
  • crossAxis — корректировка по поперечной оси (например, горизонтальной для top/bottom).
shift({
  limiter: limitShift({
    boundary: document.body,
    padding: 10,
    mainAxis: true,
    crossAxis: true
  })
});

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

Интеграция с другими middleware

Boundary constraints наиболее эффективны в комбинации с другими middleware Floating UI:

  • flip() — автоматическая смена стороны, когда пространство ограничено.
  • offset() — добавление отступов от якоря или границы.
  • arrow() — корректировка положения стрелки с учётом границ.
computePosition(reference, floating, {
  middleware: [
    offset(10),
    flip(),
    shift({ limiter: limitShift({ boundary: document.body }) }),
    arrow({ element: arrowElement })
  ]
});

При такой комбинации всплывающий элемент:

  1. Сначала сдвигается на заданный отступ.
  2. Меняет направление при нехватке места.
  3. Ограничивается границами.
  4. Стрелка корректно позиционируется относительно якоря.

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

  • Для всплывающих панелей внутри прокручиваемых контейнеров использовать контейнер как boundary, чтобы элемент не уходил за видимую область родителя.
  • При работе с модальными окнами и тултипами, которые должны оставаться в пределах окна, использовать document.body или viewport.
  • Всегда задавать padding, чтобы элементы не “прилегали” вплотную к границам, что улучшает визуальное восприятие и UX.

Особенности поведения

  • Ограничения границ применяются после flip и offset, так что элемент сначала выбирает оптимальное направление, а потом корректируется по границам.
  • Если доступного пространства недостаточно, limitShift минимизирует смещение, чтобы элемент оставался максимально видимым.
  • Middleware shift автоматически вычисляет сдвиг по основной и поперечной оси, если это разрешено настройками.

Заключение по применению

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

Настройка границ в связке с flip, offset и arrow позволяет создавать сложные всплывающие интерфейсы, которые остаются удобными и визуально аккуратными в любых условиях.