Popper.js — это библиотека для позиционирования всплывающих элементов, таких как тултипы, поповеры и dropdown-меню. На touch-устройствах возникают специфические особенности взаимодействия, которые требуют отдельного подхода при работе с Popper.js.
На устройствах с сенсорным экраном отсутствует стандартный курсор
мыши. События mouseenter и mouseleave,
привычные для десктопа, часто не срабатывают или обрабатываются с
задержкой. Вместо них используются события touchstart,
touchend и touchmove. Это важно учитывать при
активации всплывающих элементов через Popper.js.
Ключевой момент: взаимодействие должно быть основано на событиях касания, а не на hover.
Popper.js не отвечает за события активации элементов, но важно правильно интегрировать библиотеку с обработчиками событий touch. Например:
import { createPopper } from '@popperjs/core';
const button = document.querySelector('#button');
const tooltip = document.querySelector('#tooltip');
let popperInstance;
function show() {
popperInstance = createPopper(button, tooltip, {
placement: 'top',
modifiers: [
{
name: 'offset',
options: {
offset: [0, 8],
},
},
{
name: 'preventOverflow',
options: {
padding: 5,
},
},
],
});
tooltip.setAttribute('data-show', '');
}
function hide() {
tooltip.removeAttribute('data-show');
if (popperInstance) {
popperInstance.destroy();
popperInstance = null;
}
}
button.addEventListener('touchstart', (event) => {
event.preventDefault(); // предотвращает двойное срабатывание
show();
});
document.addEventListener('touchend', (event) => {
if (!button.contains(event.target)) {
hide();
}
});
Пояснения к коду:
touchstart активирует Popper, создавая всплывающий
элемент.touchend на документе позволяет скрывать Popper, если
пользователь коснулся вне элемента.preventDefault() необходим, чтобы избежать конфликтов с
click, который может сработать после touch.Для touch-устройств полезно учитывать такие жесты, как свайпы и длительное удержание. Popper.js можно использовать совместно с библиотеками распознавания жестов (например, Hammer.js) для:
longpress).// Пример использования Hammer.js
const hammer = new Hammer(button);
hammer.on('press', () => {
show();
});
hammer.on('pan', (ev) => {
if (popperInstance) {
popperInstance.update(); // пересчет позиции при движении пальца
}
});
На touch-устройствах часто приходится учитывать меньший экран и возможное наложение системной клавиатуры. В Popper.js доступны модификаторы для адаптации:
modifiers: [
{ name: 'flip', options: { fallbackPlacements: ['bottom', 'right', 'left'] } },
{ name: 'preventOverflow', options: { padding: 8 } },
{ name: 'offset', options: { offset: [0, 10] } },
]
Рекомендация: для touch-интерфейсов увеличить
padding и offset по сравнению с десктопом,
чтобы обеспечить удобный доступ к элементу.
На сенсорных устройствах возможны случайные касания, особенно при быстром скролле. Для повышения стабильности можно:
let touchTimeout;
button.addEventListener('touchstart', (event) => {
event.preventDefault();
if (touchTimeout) clearTimeout(touchTimeout);
touchTimeout = setTimeout(() => show(), 150);
});
document.addEventListener('touchend', () => {
if (touchTimeout) clearTimeout(touchTimeout);
});
На мобильных устройствах скролл может сдвинуть родительский элемент.
Popper.js имеет модификатор eventListeners, который
автоматически обновляет позицию при скролле или изменении размера
окна:
modifiers: [
{ name: 'eventListeners', enabled: true },
]
Для touch-устройств рекомендуется включать этот модификатор всегда, чтобы всплывающий элемент корректно следовал за целью при движении экрана.
touchstart вместо
mouseover.preventDefault и stopPropagation
только при необходимости, чтобы не нарушать нативное поведение
браузера.computeStyles с опцией
adaptive: true, чтобы Popper корректно реагировал на
повороты экрана и изменение размеров окна.Touch-устройства требуют более внимательной настройки Popper.js, учитывая особенности сенсорного ввода, жестов и ограниченного пространства экрана. Использование правильных модификаторов, событий и контроля жизненного цикла Popper обеспечивает стабильную и удобную работу всплывающих элементов.