Позиционирование относительно элемента

Позиционирование всплывающих подсказок в Tippy.js строится на основе библиотеки Popper (в современных версиях — Floating UI). Основная задача — вычислить оптимальное положение tooltip относительно целевого элемента (reference element), учитывая границы окна, прокрутку и доступное пространство.

Каждый tooltip привязывается к конкретному DOM-элементу и отображается в одной из сторон:

  • top
  • bottom
  • left
  • right

Дополнительно поддерживаются вариации выравнивания:

  • start — выравнивание по началу
  • end — выравнивание по концу

Пример:

tippy(button, {
  placement: 'top-start'
});

В этом случае tooltip появится сверху и будет выровнен по левому краю элемента.


Свойство placement

Ключевой параметр управления позицией — placement.

Поддерживаемые значения:

top, top-start, top-end
bottom, bottom-start, bottom-end
left, left-start, left-end
right, right-start, right-end

Пример:

tippy('.btn', {
  placement: 'right-end'
});

Особенности:

  • направление указывает сторону появления
  • суффикс (start, end) определяет выравнивание по оси

Автоматическое изменение позиции (flip)

Если заданная позиция не помещается в видимой области, Tippy автоматически пытается изменить сторону отображения.

Это поведение контролируется модификатором flip.

Пример:

tippy('.btn', {
  placement: 'top',
  popperOptions: {
    modifiers: [
      {
        name: 'flip',
        options: {
          fallbackPlacements: ['bottom', 'right']
        }
      }
    ]
  }
});

Механизм работы:

  1. Проверяется доступность позиции top
  2. Если недостаточно места — пробуется bottom
  3. Затем right

Таким образом обеспечивается адаптивность интерфейса.


Смещение (offset)

Часто требуется немного отодвинуть tooltip от элемента. Для этого используется параметр offset.

Формат:

[offsetX, offsetY]

Пример:

tippy('.btn', {
  offset: [0, 10]
});

Значения:

  • offsetX — смещение по горизонтали
  • offsetY — смещение по вертикали

Положительное значение увеличивает расстояние между tooltip и элементом.


Привязка к курсору (followCursor)

В некоторых сценариях tooltip должен следовать за курсором, а не фиксироваться относительно элемента.

tippy('.btn', {
  followCursor: true
});

Режимы:

  • true — следование по обеим осям
  • 'horizontal'
  • 'vertical'
  • 'initial' — фиксируется в позиции первого появления

Особенности:

  • позиция пересчитывается при каждом движении мыши
  • используется виртуальный reference element

Позиционирование относительно виртуального элемента

Tippy позволяет создавать tooltip без реального DOM-элемента, используя виртуальные координаты.

Пример:

tippy(document.body, {
  getReferenceClientRect: () => ({
    width: 0,
    height: 0,
    top: 100,
    bottom: 100,
    left: 200,
    right: 200
  })
});

Применение:

  • контекстные меню
  • подсказки в редакторах
  • отображение по координатам клика

Ограничение области отображения (boundary)

Tooltip не должен выходить за пределы контейнера или окна. Это контролируется через boundary.

tippy('.btn', {
  popperOptions: {
    modifiers: [
      {
        name: 'preventOverflow',
        options: {
          boundary: 'viewport'
        }
      }
    ]
  }
});

Варианты:

  • viewport — границы окна
  • window
  • конкретный DOM-элемент

Стратегия позиционирования (strategy)

Tippy поддерживает две стратегии позиционирования:

  • absolute
  • fixed
tippy('.btn', {
  popperOptions: {
    strategy: 'fixed'
  }
});

Различия:

absolute

  • зависит от ближайшего позиционированного родителя
  • учитывает прокрутку контейнеров

fixed

  • привязан к viewport
  • игнорирует прокрутку родителя

Используется при работе с фиксированными элементами интерфейса.


Влияние прокрутки и контейнеров

Позиция tooltip автоматически обновляется при:

  • прокрутке страницы
  • изменении размеров окна
  • изменении размеров элемента

Если tooltip находится внутри контейнера с overflow: hidden, возможны обрезания. Решение — использование appendTo.

tippy('.btn', {
  appendTo: document.body
});

Это выносит tooltip за пределы ограничивающего контейнера.


Точная настройка через popperOptions

Для тонкой настройки позиционирования используется popperOptions.

Пример:

tippy('.btn', {
  popperOptions: {
    modifiers: [
      {
        name: 'offset',
        options: {
          offset: [5, 15]
        }
      },
      {
        name: 'preventOverflow',
        options: {
          padding: 10
        }
      }
    ]
  }
});

Основные модификаторы:

  • offset — смещение
  • flip — смена стороны
  • preventOverflow — предотвращение выхода за границы
  • arrow — позиционирование стрелки

Позиционирование стрелки (arrow)

Стрелка автоматически выравнивается относительно tooltip и reference-элемента.

tippy('.btn', {
  arrow: true
});

Точная настройка:

tippy('.btn', {
  popperOptions: {
    modifiers: [
      {
        name: 'arrow',
        options: {
          padding: 8
        }
      }
    ]
  }
});

padding задаёт минимальное расстояние стрелки от краёв tooltip.


Динамическое изменение позиции

Позицию можно менять во время выполнения:

instance.setProps({
  placement: 'bottom'
});

Применение:

  • адаптация интерфейса
  • изменение поведения при событиях
  • реакция на пользовательские действия

Работа с inline-элементами

Для элементов, занимающих несколько строк (например, <span>), используется inlinePositioning.

tippy('.text', {
  inlinePositioning: true
});

Поведение:

  • tooltip привязывается к наиболее подходящей части текста
  • учитывается перенос строк

Позиционирование при анимации

При анимациях важно учитывать, что позиция может изменяться:

  • при scale-анимациях возможны смещения
  • рекомендуется использовать transform вместо изменения размеров

Tippy автоматически обновляет позицию при анимациях, если они влияют на layout.


Оптимизация производительности

Позиционирование — ресурсоёмкая операция. Для оптимизации:

  • избегать followCursor, если не требуется
  • ограничивать количество одновременно активных tooltip
  • использовать делегирование событий

Пример делегирования:

tippy(document.body, {
  target: '.btn'
});

Особенности работы в сложных интерфейсах

В случаях с:

  • модальными окнами
  • вложенными контейнерами
  • сложной версткой

необходимо учитывать:

  1. stacking context (z-index)
  2. clipping родительских элементов
  3. прокрутку вложенных контейнеров

Часто используется комбинация:

tippy('.btn', {
  appendTo: document.body,
  popperOptions: {
    strategy: 'fixed'
  }
});

Контроль обновления позиции

Иногда требуется вручную пересчитать позицию:

instance.popperInstance.update();

Используется при:

  • изменении размеров контента
  • динамической подгрузке данных
  • изменении DOM вне контроля Tippy

Поведение при недостатке пространства

Если ни одна из позиций не подходит:

  • tooltip сжимается
  • изменяется положение стрелки
  • применяется fallback

Контроль через:

flip: true,
fallbackPlacements: [...]

Итоговая схема работы позиционирования

  1. Определяется базовая позиция (placement)
  2. Рассчитываются координаты относительно reference-элемента
  3. Применяются модификаторы (offset, flip, preventOverflow)
  4. Учитываются границы контейнера
  5. Финальная позиция применяется через transform

Такой подход обеспечивает:

  • адаптивность
  • точность
  • стабильность отображения в различных условиях интерфейса