Ключевая возможность Shepherd.js — позиционирование шагов тура
относительно конкретных элементов интерфейса. Это реализуется через
свойство attachTo, которое определяет, к какому элементу
будет «прикреплён» попап и с какой стороны он появится.
attachTotour.addStep({
id: 'example-step',
text: 'Описание шага',
attachTo: {
element: '.my-button',
on: 'bottom'
}
});
Состав:
element — селектор DOM-элемента или сам элементon — позиция относительно элементаon)Доступные значения определяют, с какой стороны от элемента будет отображаться шаг:
| Значение | Описание |
|---|---|
top |
Сверху |
bottom |
Снизу |
left |
Слева |
right |
Справа |
top-start / top-end |
Сверху с выравниванием |
bottom-start / bottom-end |
Снизу с выравниванием |
Пример:
attachTo: {
element: '#menu',
on: 'right'
}
Вместо строки-селектора можно передать реальный DOM-узел:
const button = document.querySelector('.submit-btn');
tour.addStep({
text: 'Нажмите эту кнопку',
attachTo: {
element: button,
on: 'top'
}
});
element может быть функцией, возвращающей элемент. Это
полезно, если элемент появляется динамически:
attachTo: {
element: () => document.querySelector('.dynamic-item'),
on: 'bottom'
}
Такой подход позволяет Shepherd искать элемент в момент показа шага, а не при создании тура.
Если элемент не найден:
Контроль осуществляется через параметры:
tour.addStep({
text: 'Шаг без элемента',
attachTo: {
element: '.unknown',
on: 'top'
},
when: {
show() {
if (!document.querySelector('.unknown')) {
this.cancel();
}
}
}
});
Shepherd использует Popper.js для позиционирования, что позволяет
тонко управлять размещением через popperOptions:
tour.addStep({
text: 'Смещение шага',
attachTo: {
element: '.target',
on: 'bottom'
},
popperOptions: {
modifiers: [
{
name: 'offset',
options: {
offset: [0, 10]
}
}
]
}
});
Пояснение:
[0, 10] — смещение по X и YЕсли элемент:
display: none)важно синхронизировать показ шага:
when: {
show: () => {
const el = document.querySelector('.animated');
if (el) {
el.classList.add('visible');
}
}
}
В сложных случаях используется beforeShowPromise:
tour.addStep({
text: 'Ждём появления элемента',
attachTo: {
element: '.delayed',
on: 'bottom'
},
beforeShowPromise: () => {
return new Promise(resolve => {
const interval = setInterval(() => {
if (document.querySelector('.delayed')) {
clearInterval(interval);
resolve();
}
}, 100);
});
}
});
attachTo)Если attachTo не указан:
tour.addStep({
text: 'Общий шаг без привязки'
});
Шаг отображается по центру экрана. Это удобно для вводных или финальных сообщений.
Если селектор находит несколько элементов:
attachTo: {
element: '.item',
on: 'top'
}
Shepherd выберет первый найденный элемент.
Для точного выбора:
document.querySelectorAll('.item')[2]
Shepherd автоматически прокручивает страницу до элемента, если он вне видимой области. Это поведение настраивается:
scrollTo: true
Или более точно:
scrollTo: {
beh * avior: 'smooth',
block: 'center'
}
Если элемент находится внутри прокручиваемого контейнера:
Пример:
beforeShowPromise: () => {
return new Promise(resolve => {
const container = document.querySelector('.scroll-container');
const item = container.querySelector('.target');
container.scrollTop = item.offsetTop;
resolve();
});
}
1. Неправильный селектор
element: 'button' // слишком общий
Рекомендуется использовать уникальные селекторы (id,
data-атрибуты).
2. Элемент вне DOM на момент инициализации
Решение: использовать функцию или beforeShowPromise.
3. Перекрытие другими элементами
Иногда tooltip оказывается под другими слоями. Решение:
.shepherd-element {
z-index: 9999;
}
4. Неправильное позиционирование
Причины:
transform у родителяoverflow: hiddenPopper.js может некорректно рассчитывать позицию в таких условиях.
const tour = new Shepherd.Tour({
defaultStepOptions: {
scrollTo: true
}
});
tour.addStep({
id: 'start',
text: 'Это кнопка запуска',
attachTo: {
element: '#start-btn',
on: 'bottom'
},
buttons: [
{
text: 'Далее',
action: tour.next
}
]
});
tour.addStep({
id: 'menu',
text: 'Это меню навигации',
attachTo: {
element: '.nav-menu',
on: 'right'
}
});
data-tour,
id)beforeShowPromise для асинхронных
сценариевУсловная привязка:
attachTo: {
element: () => {
if (window.innerWidth < 768) {
return document.querySelector('.mobile-menu');
}
return document.querySelector('.desktop-menu');
},
on: 'bottom'
}
Изменение позиции на лету:
when: {
show() {
const step = this;
const isMobile = window.innerWidth < 768;
step.updateStepOptions({
attachTo: {
element: '.target',
on: isMobile ? 'bottom' : 'right'
}
});
}
}
Привязка через attachTo — фундаментальная часть
Shepherd.js, определяющая контекст каждого шага тура и его визуальную
связь с интерфейсом. Грамотное использование этого механизма напрямую
влияет на удобство и понятность пользовательского обучения.