В библиотеке Floating UI управление позиционированием элементов
осуществляется через контексты ограничений, которые
определяют, где всплывающий элемент может появляться и как реагировать
на переполнение области видимости. Основными инструментами для этого
являются параметры boundary и
rootBoundary.
boundaryboundary определяет верхнюю границу для
всплывающего элемента (floating element) относительно
переполнения. Иными словами, это элемент, в пределах которого будет
проверяться, не выходит ли всплывающее окно за пределы видимой
области.
Типы значений:
clippingParents — автоматическое
определение всех родительских элементов с CSS-свойством
overflow: hidden|scroll|auto.viewport — ограничение по видимой
области окна браузера.Пример использования:
import { computePosition, offset, flip, shift } from '@floating-ui/dom';
const reference = document.querySelector('#button');
const floating = document.querySelector('#tooltip');
computePosition(reference, floating, {
middleware: [offset(8), flip(), shift({ padding: 5 })],
strategy: 'absolute',
placement: 'bottom',
boundary: document.querySelector('#container')
}).then(({ x, y }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`
});
});
В этом примере всплывающее окно будет ограничено границами элемента с
id="container". Даже если страница прокручена или имеются
другие элементы с overflow, tooltip не выйдет
за пределы container.
Ключевые моменты о boundary:
shift позволяет корректно «подтягивать»
всплывающее окно к видимой области.rootBoundaryrootBoundary работает как абсолютный
ограничитель, игнорируя вложенные контейнеры с переполнением.
Он определяет границу для расчёта переполнения на уровне корня
документа или viewport, независимо от CSS-свойств
родителей.
Типы значений:
viewport — граница соответствует
видимой области браузера.document — учитывает весь документ,
включая скроллинг.Пример использования:
computePosition(reference, floating, {
middleware: [offset(8), flip({ padding: 10 }), shift()],
strategy: 'absolute',
placement: 'top',
boundary: document.querySelector('#modal'),
rootBoundary: 'viewport'
});
В данном случае всплывающее окно ограничено внутренними границами
#modal, но все вычисления переполнения ориентированы на
видимую область браузера (viewport).
Отличие от boundary:
boundary работает локально, в пределах выбранного
контейнера.rootBoundary задаёт глобальную рамку, к которой
привязываются все проверки переполнения и позиционирования.rootBoundary необходимо при сложных
интерфейсах с модальными окнами, порталами (portals) или динамическими
контейнерами, чтобы всплывающий элемент не «вырвался» за видимую часть
экрана.Совместное использование: Часто
boundary и rootBoundary применяются
одновременно: первый ограничивает локально, второй контролирует
глобально.
Использование с flip и
shift: Middleware flip проверяет,
можно ли разместить элемент в другом направлении, если он выходит за
boundary или rootBoundary. Middleware
shift подстраивает позицию, чтобы элемент оставался
видимым.
Порталы и модальные окна: Когда floating-элемент
рендерится в другом контейнере через портал, boundary
должен указывать на локальный контейнер, а rootBoundary —
на viewport, чтобы всплывающее окно корректно учитывало
видимую область.
Отступы и padding: Для предотвращения прилипания
к границе можно использовать padding в shift и
flip, который учитывает расстояние до boundary
и rootBoundary.
boundary — локальный ограничитель, контролирует
видимость floating-элемента внутри конкретного контейнера.rootBoundary — глобальный ограничитель, определяет
расчет переполнения на уровне документа или окна браузера.