Popper.js — это мощная библиотека для позиционирования элементов относительно других элементов на странице. Она идеально подходит для создания интерактивных компонентов, таких как dropdown-меню, тултипы, всплывающие подсказки и модальные окна. Рассмотрим подробно, как использовать Popper.js для dropdown-компонентов.
Для начала необходимо подключить библиотеку Popper.js (версии 2.x) через npm или CDN. Основная задача Popper — вычислять позицию popper-элемента относительно reference-элемента. В контексте dropdown reference — это кнопка или другой элемент, по которому открывается меню.
import { createPopper } from '@popperjs/core';
const button = document.querySelector('#dropdownButton');
const menu = document.querySelector('#dropdownMenu');
const popperInstance = createPopper(button, menu, {
placement: 'bottom-start', // Позиция меню относительно кнопки
modifiers: [
{
name: 'offset',
options: {
offset: [0, 8], // Смещение по горизонтали и вертикали
},
},
{
name: 'flip',
options: {
fallbackPlacements: ['top-start', 'right-start', 'left-start'],
},
},
{
name: 'preventOverflow',
options: {
boundary: 'viewport', // Ограничение выхода за границы окна
},
},
],
});
Ключевые моменты:
placement задаёт базовую позицию dropdown относительно
reference.offset позволяет сдвигать меню от
reference, чтобы избежать наложения.flip автоматически меняет положение, если
dropdown не помещается на экране.preventOverflow предотвращает выход dropdown за границы
viewport или другого контейнера.Popper.js отвечает только за позиционирование, поэтому показ и скрытие меню необходимо реализовать отдельно через JS:
button.addEventListener('click', () => {
menu.classList.toggle('show'); // Класс 'show' отображает меню
popperInstance.update(); // Обновление позиции при открытии
});
document.addEventListener('click', (event) => {
if (!button.contains(event.target) && !menu.contains(event.target)) {
menu.classList.remove('show');
}
});
Особенности:
popperInstance.update() гарантирует корректное
позиционирование при изменении размеров кнопки или меню.Popper.js не накладывает ограничения на стили, поэтому можно комбинировать с CSS для плавного открытия:
#dropdownMenu {
opacity: 0;
transform: scaleY(0);
transform-origin: top;
transition: opacity 0.2s ease, transform 0.2s ease;
}
#dropdownMenu.show {
opacity: 1;
transform: scaleY(1);
}
Такой подход позволяет добиться эффектного появления dropdown с сохранением точного позиционирования.
Popper.js поддерживает динамические reference и popper-элементы. Можно создавать dropdown на лету:
function createDropdown(referenceElement, content) {
const menu = document.createElement('div');
menu.className = 'dropdown-menu';
menu.innerHTML = content;
document.body.appendChild(menu);
const instance = createPopper(referenceElement, menu, {
placement: 'bottom-start',
modifiers: [
{ name: 'offset', options: { offset: [0, 4] } },
],
});
return { menu, instance };
}
Преимущества:
Popper.js предоставляет хуки через модификаторы для реакции на изменение позиции:
const popperInstance = createPopper(button, menu, {
placement: 'bottom-start',
modifiers: [
{
name: 'eventListeners',
enabled: true,
},
{
name: 'applyStyles',
fn({ state }) {
console.log('Новая позиция:', state.styles.popper);
},
},
],
});
Это полезно для интеграции с анимациями, адаптивным дизайном или кастомными эффектами.
Dropdown на мобильных требует учёта размеров экрана и сенсорного
ввода. Popper.js можно настроить через preventOverflow и
flip:
modifiers: [
{ name: 'preventOverflow', options: { boundary: 'viewport', padding: 8 } },
{ name: 'flip', options: { fallbackPlacements: ['top', 'left', 'right'] } },
]
padding предотвращает прилипание меню к краям
экрана.fallbackPlacements задаёт альтернативные позиции для
корректного отображения на малых экранах.popperInstance.destroy()), чтобы снизить
нагрузку.modifiers: [{ name: 'computeStyles', options: { gpuAcceleration: true } }]
для плавной анимации.