Стратегии referenceHidden и escaped

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


Стратегия referenceHidden

referenceHidden используется для отслеживания состояния элемента-эталона (reference) относительно viewport или его ближайшего scrollable контейнера. Она определяет, следует ли считать плавающий элемент скрытым, если reference перестаёт быть видимым.

Основные принципы работы:

  1. Определение скрытого состояния Элемент считается скрытым, когда:

    • Его bounding rectangle полностью выходит за пределы viewport.
    • Он находится за пределами scrollable контейнера.
  2. Применение через middleware В Floating UI это реализуется как middleware hide({ strategy: 'referenceHidden' }):

    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(),
        hide({ strategy: 'referenceHidden' })
      ]
    }).then(({ x, y, middlewareData }) => {
      Object.assign(floating.style, {
        left: `${x}px`,
        top: `${y}px`,
        visibility: middlewareData.hide.referenceHidden ? 'hidden' : 'visible'
      });
    });

    В этом примере middlewareData.hide.referenceHidden возвращает true, если reference скрыт. Это позволяет управлять видимостью плавающего элемента без необходимости вручную отслеживать скролл и размеры viewport.

  3. Практическое применение

    • Тултипы и подсказки, которые должны исчезать при скролле или прокрутке.
    • Плавающие меню, которые не должны отображаться, когда их reference не виден.

Стратегия escaped

escaped отслеживает, вышел ли плавающий элемент за пределы видимой области контейнера или viewport, независимо от состояния reference. Эта стратегия особенно полезна для предотвращения обрезания элементов или их некорректного отображения.

Основные принципы работы:

  1. Определение состояния выхода Элемент считается вышедшим, если его bounding rectangle частично или полностью выходит за пределы viewport или контейнера, установленного через strategy.

  2. Применение через middleware

    import { computePosition, hide } from '@floating-ui/dom';
    
    const reference = document.querySelector('#input');
    const floating = document.querySelector('#dropdown');
    
    computePosition(reference, floating, {
      middleware: [
        hide({ strategy: 'escaped' })
      ]
    }).then(({ x, y, middlewareData }) => {
      Object.assign(floating.style, {
        left: `${x}px`,
        top: `${y}px`,
        visibility: middlewareData.hide.escaped ? 'hidden' : 'visible'
      });
    });

    Здесь middlewareData.hide.escaped возвращает true, если плавающий элемент выходит за границы видимой области. Это удобно для динамических элементов, которые должны оставаться полностью в пределах экрана.

  3. Практическое применение

    • Плавающие меню с динамическими позициями, где важно, чтобы элемент не обрезался.
    • Tooltip-ы на мобильных устройствах, где размеры viewport часто меняются при повороте экрана.
    • Модальные окна или кастомные dropdown’ы, чтобы избежать перекрытия критически важных элементов интерфейса.

Отличия referenceHidden и escaped

Характеристика referenceHidden escaped
Отслеживаемый объект Reference элемент Плавающий элемент
Причина скрытия Reference ушел за пределы видимости Floating вышел за пределы контейнера
MiddlewareData ключ middlewareData.hide.referenceHidden middlewareData.hide.escaped
Типичный сценарий Тултипы, подсказки Dropdown, модальные окна

Рекомендации по использованию

  • Сочетание стратегий: Часто применяют обе стратегии одновременно для максимальной надежности. Например, тултип можно скрывать и когда reference скрыт, и когда сам тултип выходит за viewport:
hide({ strategy: 'referenceHidden' }),
hide({ strategy: 'escaped' })
  • Производительность: Стратегия escaped может потребовать больше вычислений, особенно при частых изменениях размеров контейнера или viewport. Для элементов с высокой частотой ререндеринга лучше комбинировать с requestAnimationFrame или debounce.

  • Совместимость с flip и shift: Middleware hide идеально работает вместе с flip и shift, корректируя позицию перед проверкой видимости.


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