Блокировка прокрутки

Shepherd.js предоставляет мощный инструмент для создания интерактивных туров по интерфейсу. Одной из ключевых возможностей является блокировка прокрутки страницы во время показа подсказок. Это позволяет сфокусировать внимание пользователя на конкретном элементе и предотвратить случайное смещение контента.

Включение блокировки прокрутки

Для активации блокировки прокрутки используется свойство scrollTo и соответствующие настройки в шаге тура. По умолчанию Shepherd автоматически прокручивает страницу к элементу, на который ссылается шаг, но можно комбинировать это с блокировкой прокрутки.

Пример конфигурации шага с блокировкой прокрутки:

const tour = new Shepherd.Tour({
  defaultStepOptions: {
    scrollTo: false,
    useModalOverlay: true
  }
});

tour.addStep({
  id: 'example-step',
  text: 'Это шаг с блокировкой прокрутки',
  attachTo: {
    element: '#target-element',
    on: 'bottom'
  },
  beforeShowPromise: () => {
    document.body.style.overflow = 'hidden'; // Блокировка прокрутки
    return Promise.resolve();
  },
  when: {
    hide: () => {
      document.body.style.overflow = ''; // Восстановление прокрутки
    }
  }
});

В этом примере используется комбинация beforeShowPromise и события hide, чтобы временно отключить прокрутку документа, а после скрытия шага восстановить стандартное поведение.

Использование useModalOverlay

Свойство useModalOverlay автоматически создает полупрозрачный оверлей и предотвращает взаимодействие с другими элементами страницы. Когда оно включено, Shepherd.js частично блокирует прокрутку, но не всегда полностью предотвращает движение страницы при скролле колесиком мыши. Для полной блокировки рекомендуется дополнительно устанавливать overflow: hidden на <body> или <html>.

Полная блокировка скролла при всех шагах тура

Чтобы заблокировать прокрутку на всем туре, можно использовать глобальные события тура:

const tour = new Shepherd.Tour({
  defaultStepOptions: {
    scrollTo: false
  }
});

tour.on('start', () => {
  document.body.style.overflow = 'hidden';
});

tour.on('complete', () => {
  document.body.style.overflow = '';
});

tour.on('cancel', () => {
  document.body.style.overflow = '';
});

Такой подход гарантирует, что независимо от шага, прокрутка будет заблокирована до завершения или отмены тура.

Настройка прокрутки отдельного шага

Иногда необходимо, чтобы один шаг тура был зафиксирован, а другие позволяли прокрутку. Для этого используется scrollTo: false в конфигурации шага и ручное управление overflow через события шага. Пример:

tour.addStep({
  id: 'fixed-step',
  text: 'Этот шаг блокирует прокрутку',
  attachTo: { element: '#fixed-element', on: 'top' },
  beforeShowPromise: () => {
    document.body.style.overflow = 'hidden';
    return Promise.resolve();
  },
  when: {
    hide: () => {
      document.body.style.overflow = '';
    }
  }
});

Совмещение с мобильными устройствами

На мобильных устройствах блокировка прокрутки требует дополнительного внимания. Достаточно установить CSS:

body.tour-active {
  overflow: hidden;
  position: fixed;
  width: 100%;
}

И в коде JavaScript добавлять класс при старте тура:

tour.on('start', () => {
  document.body.classList.add('tour-active');
});

tour.on('complete', () => {
  document.body.classList.remove('tour-active');
});

tour.on('cancel', () => {
  document.body.classList.remove('tour-active');
});

Этот метод предотвращает скролл контента при жестах на мобильных устройствах, которые иначе могут игнорировать overflow: hidden.

Управление прокруткой внутри контейнеров

Если интерфейс использует прокручиваемые контейнеры (overflow: auto или scroll), блокировка прокрутки через <body> не действует. В этом случае можно:

  • Найти контейнер, который прокручивается.
  • Установить для него overflow: hidden на время шага.
  • Восстановить значение после скрытия шага.

Пример для контейнера #scrollable-div:

beforeShowPromise: () => {
  const container = document.querySelector('#scrollable-div');
  container.dataset.prevOverflow = container.style.overflow;
  container.style.overflow = 'hidden';
  return Promise.resolve();
},
when: {
  hide: () => {
    const container = document.querySelector('#scrollable-div');
    container.style.overflow = container.dataset.prevOverflow || '';
  }
}

Рекомендации по UX

  • Блокировка прокрутки должна быть краткой и применяться только на шагах, где это действительно необходимо.
  • При использовании оверлея (useModalOverlay) блокировка прокрутки усиливает эффект фокусировки, но не заменяет ручную блокировку.
  • На мобильных устройствах рекомендуется использовать класс position: fixed, чтобы исключить подергивание контента при жестах.

Блокировка прокрутки в Shepherd.js — гибкий инструмент, который позволяет управлять вниманием пользователя, создавать более понятные и структурированные туры, а также предотвращать случайные взаимодействия с интерфейсом.