Popper.js — это мощная библиотека для управления позиционированием всплывающих элементов относительно их «опорных» элементов. В контексте sel ect-компонентов она используется для корректного отображения выпадающих списков опций независимо от размеров окна, прокрутки страницы или положения родительского элемента.
Главная концепция Popper.js заключается в создании поппера — элемента, который «прилипает» к целевому элементу (reference) с возможностью динамического смещения и переноса при необходимости.
import { createPopper } fr om '@popperjs/core';
const button = document.querySelector('#select-button');
const dropdown = document.querySelector('#select-dropdown');
createPopper(button, dropdown, {
placement: 'bottom-start',
});
placement определяет начальное
позиционирование (top, bottom,
left, right) с опциональными уточнениями
(start, end).Popper.js использует модификаторы, которые изменяют поведение поппера. Для select-списков наиболее важные:
createPopper(button, dropdown, {
placement: 'bottom-start',
modifiers: [
{
name: 'offset',
options: {
offset: [0, 8], // [по горизонтали, по вертикали]
},
},
],
});
modifiers: [
{
name: 'flip',
options: {
fallbackPlacements: ['top-start', 'right-start'],
},
},
]
modifiers: [
{
name: 'preventOverflow',
options: {
padding: 8, // отступ от края экрана
},
},
]
transform или top/left
для позиционирования:modifiers: [
{
name: 'computeStyles',
options: {
adaptive: true, // меняет position при прокрутке
gpuAcceleration: true, // ускоряет анимацию
},
},
]
В select-компонентах содержимое списка часто изменяется динамически. Popper.js предоставляет методы обновления позиции поппера:
const popperInstance = createPopper(button, dropdown, { placement: 'bottom-start' });
// при изменении содержимого списка
popperInstance.update();
Если список становится выше или ниже, чем ожидалось,
update() перерассчитывает все параметры и корректно
отображает dropdown.
Popper.js поддерживает виртуальные reference-элементы, что полезно для кастомных селектов, где trigger не является реальным DOM-элементом:
const virtualReference = {
getBoundingClientRect: () => ({
width: 100,
height: 40,
top: 200,
right: 300,
bottom: 240,
left: 200,
}),
contextElement: document.body,
};
createPopper(virtualReference, dropdown, { placement: 'bottom' });
Такой подход позволяет позиционировать dropdown даже относительно координат, полученных из пользовательских вычислений.
Для мобильных устройств важно учитывать, что viewport часто меняется при появлении клавиатуры. Рекомендуется использовать комбинацию модификаторов:
flip для выбора альтернативного положения.preventOverflow с padding для безопасного расстояния от
краев экрана.eventListeners для обновления позиции при прокрутке или
ресайзе:modifiers: [
{
name: 'eventListeners',
options: {
scroll: true,
resize: true,
},
},
]
Popper.js сам по себе не управляет анимацией, но позволяет безопасно комбинировать позиционирование с CSS-анимациями:
#select-dropdown {
opacity: 0;
transform: scaleY(0);
transform-origin: top;
transition: opacity 0.2s ease, transform 0.2s ease;
}
#select-dropdown.show {
opacity: 1;
transform: scaleY(1);
}
button.addEventListener('click', () => {
dropdown.classList.toggle('show');
popperInstance.update();
});
Важно вызывать update() после изменения класса, чтобы
Popper пересчитал размеры и корректно отобразил dropdown.
Dropdown с прокручиваемым контентом Использовать
preventOverflow с
boundariesElement: 'viewport' или кастомным
контейнером.
Многоуровневые меню Для вложенных списков можно создавать отдельные Popper-инстансы, привязанные к родительской опции.
Динамическое изменение reference При смене
кнопки или позиции элемента достаточно вызвать
popperInstance.setOptions({}) и update() для
пересчета.
Popper.js обеспечивает максимальную гибкость позиционирования для select-компонентов, позволяя создавать адаптивные, динамические и надежные выпадающие списки с точным управлением смещением, границами и поведением при ограниченном пространстве.