В библиотеке Floating UI управление видимостью всплывающих элементов
при выходе за пределы контейнера осуществляется с помощью
middleware hide. Этот middleware позволяет
автоматически скрывать floating-элемент, если он оказывается за
пределами видимой области или выходит за рамки определённого
ограничения.
import { computePosition, offset, flip, shift, hide } from '@floating-ui/dom';
const reference = document.querySelector('#button');
const floating = document.querySelector('#tooltip');
computePosition(reference, floating, {
middleware: [offset(8), flip(), shift({ padding: 5 }), hide()]
}).then(({ x, y, middlewareData }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`,
visibility: middlewareData.hide?.referenceHidden ? 'hidden' : 'visible'
});
});
В этом примере hide() проверяет два основных
состояния:
Значения этих флагов можно использовать для динамического управления стилями и поведением всплывающего элемента.
Middleware hide поддерживает параметр
boundary, который задаёт область, относительно которой
происходит проверка выхода. Это может быть:
hide({ boundary: document.querySelector('#container') })
Параметр strategy определяет, как рассчитываются границы:
absolute – расчёт относительно документа.fixed – расчёт относительно viewport.Использование strategy полезно при работе с
позиционированными контейнерами или модальными окнами.
Скрытие при выходе за границы часто комбинируется с flip
и shift, чтобы floating-элемент корректно reposition-ился
перед тем, как исчезнуть.
flip() меняет сторону отображения, если элемент выходит
за границы.shift() смещает элемент внутрь видимой области.hide() реагирует на крайний случай, когда reposition
невозможен.middleware: [
offset(10),
flip(),
shift({ padding: 8 }),
hide({ boundary: document.body })
]
В такой цепочке hide срабатывает только после всех
попыток корректного позиционирования.
Скрытие можно синхронизировать с событиями, например, при скролле или
ресайзе окна. Для этого достаточно повторно вызывать
computePosition и обновлять свойство
visibility:
window.addEventListener('scroll', updatePosition);
window.addEventListener('resize', updatePosition);
function updatePosition() {
computePosition(reference, floating, { middleware: [offset(8), flip(), hide()] })
.then(({ x, y, middlewareData }) => {
Object.assign(floating.style, {
left: `${x}px`,
top: `${y}px`,
visibility: middlewareData.hide?.referenceHidden ? 'hidden' : 'visible'
});
});
}
Такое решение позволяет поддерживать актуальное состояние видимости независимо от движения элементов на странице.
hide всегда вместе с flip и
shift, чтобы минимизировать внезапное исчезновение
элементов.middlewareData.hide перед изменением
visibility, чтобы избежать лишних перерисовок.hide с разными boundary для точного контроля
поведения.hide обеспечивает автоматическую реакцию на
ограничение видимости, делая интерфейс гибким и предотвращая
случайное “вылетание” всплывающих элементов за пределы экрана или
контейнера.