Popper.js — это библиотека для позиционирования элементов на странице относительно других элементов. Основная задача библиотеки — управление всплывающими элементами (tooltips, dropdowns, popovers) так, чтобы они корректно позиционировались даже при изменении размера окна или динамическом изменении DOM.
Ключевой принцип Popper.js — отделение вычисления позиции от её применения в DOM. Это позволяет фреймворкам интегрировать Popper.js в свои жизненные циклы и управлять позиционированием элементов без лишнего вмешательства в рендеринг.
Создание поппера осуществляется с помощью функции
createPopper(reference, popper, options).
Пример базовой инициализации:
import { createPopper } from '@popperjs/core';
const button = document.querySelector('#button');
const tooltip = document.querySelector('#tooltip');
const popperInstance = createPopper(button, tooltip, {
placement: 'top',
modifiers: [
{
name: 'offset',
options: {
offset: [0, 8],
},
},
{
name: 'preventOverflow',
options: {
boundary: 'viewport',
},
},
],
});
Важные моменты:
placement определяет, где будет появляться поппер
относительно reference (top, bottom,
left, right).createPopper возвращает объект с методами управления
жизненным циклом: update(), destroy() и
setOptions().Popper.js предоставляет три ключевых метода жизненного цикла:
placement и модификаторы.popperInstance.setOptions({
placement: 'bottom',
});
popperInstance.update();
Метод setOptions полезен для реактивных фреймворков, где
состояние может изменяться асинхронно. После обновления опций вызов
update() гарантирует, что элемент займёт корректное
положение.
Во фреймворках жизненный цикл компонентов (mount, update, unmount) тесно связан с Popper.js:
createPopper.update() или setOptions().destroy(), чтобы
удалить слушатели и предотвратить утечки памяти.import { useEffect, useRef } from 'react';
import { createPopper } from '@popperjs/core';
function Tooltip({ referenceElement, content }) {
const popperRef = useRef(null);
const instanceRef = useRef(null);
useEffect(() => {
if (referenceElement && popperRef.current) {
instanceRef.current = createPopper(referenceElement, popperRef.current, {
placement: 'top',
modifiers: [{ name: 'offset', options: { offset: [0, 10] } }],
});
}
return () => {
instanceRef.current?.destroy();
instanceRef.current = null;
};
}, [referenceElement]);
return <div ref={popperRef}>{content}</div>;
}
В этом примере:
useEffect, что
соответствует фазе mount.unmount.setOptions()
и update().Модификаторы позволяют управлять каждым аспектом позиционирования:
Каждый модификатор имеет фазу выполнения: read,
beforeMain, main, afterMain,
write. Это позволяет фреймворкам точно контролировать,
когда происходят вычисления и изменения DOM.
Popper.js поддерживает асинхронное обновление через метод
update() или через флаг async: true в
модификаторах. Это критично для динамически изменяющихся интерфейсов,
где размеры reference могут изменяться после рендера.
popperInstance.update().then(() => {
console.log('Popper position updated');
});
Использование промисов гарантирует, что обновление завершилось до применения новых вычисленных координат, предотвращая визуальные «скачки» элементов.
Popper.js, интегрированный во фреймворки, работает как связующее
звено между состоянием компонента и визуальной компоновкой элементов.
Правильное управление методами createPopper,
update, setOptions и destroy
обеспечивает:
Комплексное использование этих методов вместе с модификаторами позволяет создавать высоконадежные интерфейсы с динамическими всплывающими элементами, которые адаптируются к любым изменениям DOM и окна браузера.