В Popper.js ключевым аспектом является позиционирование всплывающих элементов относительно целевых (reference) элементов. Стандартный подход использует реальные DOM-узлы, однако для сложных интерфейсов часто необходимы виртуальные элементы, которые не существуют в DOM, но служат якорями для всплывающих подсказок, тултипов или контекстных меню. Popper.js поддерживает виртуальные элементы через объект с минимальным набором свойств, позволяя создавать динамические интерфейсы без привязки к физическим DOM-элементам.
Виртуальный элемент представляет собой объект с обязательным методом
getBoundingClientRect. Простейший пример:
const virtualElement = {
getBoundingClientRect: () => ({
top: 100,
left: 150,
right: 250,
bottom: 200,
width: 100,
height: 100,
}),
contextElement: document.body, // опционально
};
Ключевые моменты:
getBoundingClientRect должен возвращать объект,
аналогичный DOMRect, с координатами относительно окна просмотра.contextElement определяет базовый контейнер для
Popper.js. Если не задан, используется document.body.Попперы создаются стандартным образом:
import { createPopper } from '@popperjs/core';
const popperInstance = createPopper(virtualElement, tooltipElement, {
placement: 'top',
modifiers: [
{
name: 'offset',
options: {
offset: [0, 10],
},
},
],
});
Особенность здесь в том, что Popper не требует DOM-узла для reference, что открывает возможности для привязки подсказок к координатам мыши, кастомным виртуальным областям или элементам, которые будут добавлены в DOM позже.
Для динамических интерфейсов координаты виртуального элемента можно менять на лету. Например, для подсказки, которая следует за мышью:
document.addEventListener('mousemove', (event) => {
virtualElement.getBoundingClientRect = () => ({
top: event.clientY,
left: event.clientX,
right: event.clientX,
bottom: event.clientY,
width: 0,
height: 0,
});
popperInstance.update();
});
Особенности:
update.eventListeners для автоматического обновления.Виртуальные элементы поддерживают все модификаторы, которые применяются к реальным DOM-узлам:
Пример:
const popperInstance = createPopper(virtualElement, tooltipElement, {
placement: 'right',
modifiers: [
{ name: 'flip', options: { fallbackPlacements: ['left', 'top'] } },
{ name: 'preventOverflow', options: { padding: 8 } },
],
});
В этом случае, даже виртуальный элемент корректно взаимодействует с системой ограничения и автоматической перестановки.
Иногда необходимо задавать ширину и высоту виртуального элемента, чтобы Popper мог правильно позиционировать тултип:
const virtualElement = {
getBoundingClientRect: () => ({
top: 200,
left: 300,
right: 350,
bottom: 250,
width: 50,
height: 50,
}),
};
Popper использует width и height для
точного расчета смещений и размеров всплывающих блоков, особенно когда
применяется модификатор preventOverflow.
update при
изменении координат.computeStyles с опцией
gpuAcceleration: true.Виртуальные элементы открывают новый уровень контроля над позиционированием всплывающих элементов в Popper.js, позволяя строить динамические интерфейсы, свободные от ограничений DOM, с полной поддержкой стандартных модификаторов, смещений и адаптивного поведения.