Padding для стрелки

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


Параметр arrow.padding

arrow.padding задает внутренний отступ между стрелкой и границей всплывающего элемента. Его основная цель — предотвратить наложение стрелки на край контейнера и сохранить визуальную гармонию. Значение может быть указано как число (в пикселях) или как объект с указанием сторон:

import { computePosition, offset, flip, shift, arrow } from '@floating-ui/dom';

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

computePosition(reference, floating, {
  middleware: [
    offset(10),
    flip(),
    shift(),
    arrow({ element: arrowElement, padding: 5 }) // стрелка отстоит на 5px от края
  ]
}).then(({ x, y, placement, middlewareData }) => {
  Object.assign(floating.style, {
    left: `${x}px`,
    top: `${y}px`
  });

  const { x: arrowX, y: arrowY } = middlewareData.arrow;
  Object.assign(arrowElement.style, {
    left: arrowX != null ? `${arrowX}px` : '',
    top: arrowY != null ? `${arrowY}px` : ''
  });
});

Ключевые моменты:

  • padding: 5 гарантирует, что стрелка не будет примыкать прямо к краю тултипа.
  • padding можно задавать как объект { top: 5, right: 10, bottom: 5, left: 10 }, что позволяет раздельно управлять отступами по сторонам.
  • Значение учитывается при расчете позиции стрелки на основе текущего placement.

Влияние arrow.padding на поведение

  1. Смещенные края При малом отступе стрелка может пересекать рамку элемента, создавая визуальный дисбаланс. Увеличение padding исправляет это и обеспечивает безопасное расстояние.

  2. Адаптация к shift и flip Middleware shift и flip перемещают элемент при нехватке пространства. arrow.padding корректирует конечную позицию стрелки, не позволяя ей выходить за пределы видимого контейнера.

  3. Динамическая подстройка при изменении размеров Если размер элемента изменяется (например, текст в тултипе становится длиннее), стрелка автоматически сохраняет заданный отступ, сохраняя эстетичное позиционирование.


Использование разных значений padding

  • Число: единое расстояние от всех краев стрелки.

    arrow({ element: arrowElement, padding: 8 })
  • Объект: индивидуальные отступы по сторонам.

    arrow({ element: arrowElement, padding: { top: 5, bottom: 10 } })
  • Функция: позволяет вычислять padding динамически в зависимости от состояния.

    arrow({ 
      element: arrowElement, 
      padding: ({ placement }) => placement.startsWith('top') ? 10 : 5 
    })

Практические рекомендации

  • Для небольших всплывающих элементов достаточно padding 4–6px, чтобы стрелка выглядела аккуратно.
  • Для крупных поповеров или меню лучше использовать 8–12px, особенно если есть скругления углов.
  • При сложных макетах с ограниченным пространством полезно использовать arrow.padding вместе с shift() и flip(), чтобы стрелка не выходила за границы окна.

Распространенные ошибки

  • Игнорирование padding: стрелка может “вырезать” угол тултипа, нарушая дизайн.
  • Неправильное сочетание с offset: слишком большой offset вместе с минимальным padding может привести к тому, что стрелка визуально отделится от элемента.
  • Фиксированное значение при адаптивной верстке: при изменении размеров экрана стрелка может смещаться некорректно. Решение — использовать функцию для динамического расчета.

Интеграция с другими middleware

arrow.padding работает в связке с:

  • offset() — регулирует расстояние между тултипом и якорем.
  • flip() — меняет позицию тултипа при нехватке места.
  • shift() — смещает элемент, чтобы он оставался видимым.

Правильная комбинация этих middleware с корректным padding гарантирует точное и эстетичное позиционирование стрелки вне зависимости от размеров экрана или контейнера.