Определение видимости элемента

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

Видимость элемента определяется не только его отображением через CSS-свойства (display, visibility, opacity), но и положением в viewport, перекрытием другими элементами и условиями выхода за границы контейнера. Floating UI учитывает эти аспекты через систему middleware, которая позволяет модифицировать или анализировать позицию “плавающего” элемента.


Middleware detectOverflow

Ключевой инструмент для определения видимости — middleware detectOverflow. Он проверяет, выходит ли элемент за пределы заданного контейнера (например, окна браузера или родительского блока) и возвращает объект с информацией о превышении по каждой стороне:

import { computePosition, detectOverflow } from '@floating-ui/dom';

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

computePosition(reference, floating, {
  middleware: [
    detectOverflow()
  ]
}).then(({ x, y, middlewareData }) => {
  console.log(middlewareData.detectOverflow);
});

Объект middlewareData.detectOverflow содержит значения для всех четырёх сторон:

  • top — сколько пикселей элемент вышел за верхнюю границу.
  • bottom — за нижнюю.
  • left — за левую.
  • right — за правую.

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


Параметры detectOverflow

Middleware detectOverflow поддерживает настройку через объект опций:

  • boundary — элемент или массив элементов, ограничивающих видимость. По умолчанию это document.body.
  • rootBoundaryviewport или document — определяет глобальные границы.
  • padding — отступ, учитываемый при проверке. Позволяет не считать элемент перекрытым, если он находится на небольшом расстоянии от края.
  • altBoundary — позволяет учитывать альтернативный контейнер при вычислении выхода за границы.

Пример использования с отступом и альтернативным контейнером:

detectOverflow({
  boundary: document.querySelector('#container'),
  padding: 8,
  altBoundary: document.querySelector('#scrollable')
});

Обработка частичной видимости

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

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

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

Middleware shift автоматически смещает элемент, чтобы он полностью поместился в границы контейнера. Использование detectOverflow вместе с shift позволяет реализовать динамическую видимость и избегать обрезания элементов на экране.


Совмещение с flip и autoPlacement

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

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

computePosition(reference, floating, {
  middleware: [
    detectOverflow(),
    flip(),
    autoPlacement({ alignment: 'start' })
  ]
});
  • flip() проверяет все альтернативные позиции и выбирает ту, которая полностью видна.
  • autoPlacement() учитывает предпочтительное выравнивание (start, end, center) и изменяет положение в зависимости от доступного пространства.

Рекомендации по оптимизации

  1. Использовать detectOverflow с точной границей — если контейнер имеет прокрутку, указывать его явно в boundary.
  2. Комбинировать с shift и flip — для предотвращения обрезания элементов и обеспечения адаптивного поведения.
  3. Следить за производительностью — при работе с большим количеством элементов избегать частых вызовов computePosition, особенно на scroll- или resize-событиях. Оптимально использовать requestAnimationFrame или throttling.
  4. Учитывать динамическое содержимое — изменения размеров элементов должны инициировать повторное вычисление позиции и видимости.

Примеры использования в реальном интерфейсе

  • Всплывающие подсказки (tooltips) — всегда остаются в пределах видимой области, даже если кнопка находится в нижней части экрана.
  • Контекстные меню — автоматически смещаются при приближении к краям окна, предотвращая обрезание пунктов.
  • Дропдауны и селекты — можно комбинировать с scrollable containers, чтобы элемент оставался видимым при прокрутке.

Использование detectOverflow и связанных middleware обеспечивает точный контроль видимости элементов на странице, позволяя создавать интерфейсы с динамическим и адаптивным позиционированием.