Sticky-позиционирование во Floating UI применяется для закрепления
плавающего элемента (floating element) относительно якорного (reference
element) в пределах заданной области. В отличие от классического CSS
position: sticky, библиотека реализует более гибкий
механизм, учитывающий столкновения с границами, прокрутку контейнеров и
изменение размеров.
Основная задача — обеспечить поведение, при котором floating-элемент “прилипает” к границе, когда достигает её, но остаётся связанным с reference-элементом, пока это возможно.
Sticky-логика строится поверх вычисления координат через
computePosition. Floating UI отслеживает:
При достижении границы активируется ограничение движения floating-элемента.
shiftSticky-поведение чаще всего реализуется через middleware
shift, который отвечает за сдвиг элемента внутри доступной
области.
import { computePosition, shift } from '@floating-ui/dom';
computePosition(referenceEl, floatingEl, {
middleware: [
shift({
padding: 8
})
]
});
Что происходит:
Для более точного sticky-поведения используется limiter.
Он задаёт правила, насколько далеко элемент может смещаться.
import { shift, limitShift } from '@floating-ui/dom';
shift({
limiter: limitShift()
});
По умолчанию limitShift не позволяет элементу полностью
оторваться от reference.
В некоторых сценариях требуется ограничить движение только по одной оси:
shift({
mainAxis: true,
crossAxis: false
});
mainAxis — основная ось (например, вертикаль при
placement: 'top')crossAxis — поперечная осьЭто позволяет реализовать поведение, близкое к CSS sticky по вертикали или горизонтали.
Floating UI умеет учитывать не только viewport, но и вложенные контейнеры с прокруткой.
computePosition(referenceEl, floatingEl, {
middleware: [
shift({
boundary: containerEl
})
]
});
Особенности:
Чтобы избежать прилипания вплотную к краю, используется padding:
shift({
padding: {
top: 10,
bottom: 10,
left: 5,
right: 5
}
});
Это создаёт “зону безопасности”, в пределах которой элемент может свободно двигаться.
Sticky-поведение редко используется изолированно. Обычно оно комбинируется:
Добавляет отступ от reference:
offset(8)
Меняет сторону при нехватке места:
flip()
Фиксирует внутри границ:
shift()
Пример полной конфигурации:
computePosition(referenceEl, floatingEl, {
placement: 'bottom',
middleware: [
offset(8),
flip(),
shift({
padding: 8,
limiter: limitShift()
})
]
});
Floating UI пересчитывает позицию при изменениях:
Для этого используется autoUpdate:
import { autoUpdate } from '@floating-ui/dom';
autoUpdate(referenceEl, floatingEl, () => {
computePosition(referenceEl, floatingEl, {
middleware: [shift()]
}).then(({ x, y }) => {
Object.assign(floatingEl.style, {
left: `${x}px`,
top: `${y}px`
});
});
});
Это обеспечивает “живое” sticky-поведение.
1. Отсутствие реального CSS sticky Floating UI не изменяет поток документа — позиционирование всегда абсолютное или фиксированное.
2. Производительность Частые пересчёты могут быть затратными при большом количестве элементов.
3. Вложенные контейнеры Важно корректно задавать
boundary, иначе поведение может казаться “ломаным”.
shift({
boundary: 'viewport'
});
shift({
limiter: limitShift({
offset: 0
})
});
Комбинация:
shift с ограничениямиmainAxisАлгоритм sticky-позиционирования:
computePosition)shift)limiter)| Характеристика | CSS sticky | Floating UI sticky |
|---|---|---|
| Привязка к DOM | Да | Нет |
| Контроль логики | Ограниченный | Полный |
| Работа с тултипами | Нет | Да |
| Гибкость | Низкая | Высокая |
| Поддержка контейнеров | Частичная | Полная |
Sticky-позиционирование во Floating UI — это не отдельный режим, а
результат комбинации middleware, где ключевую роль играет
shift и его ограничители.