Как программно прокрутить горизонтально, не прокручивая вертикально?

Вопрос или проблема

Я пытаюсь создать простой слайдер изображений с постепенным улучшением. Код здесь.

Базовая версия полностью функционирует без JavaScript: используя якорные ссылки, флексбокс и scroll-snap-align, поведение уже довольно приятное и функционально завершенное.

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

Очевидная попытка — это использовать preventDefault() при изменении хеша в URL (т.е. когда щелкают по ссылкам) и выполнить scrollTo() на JavaScript с опцией top, установленной на текущее положение прокрутки.

Вот мой код JavaScript:

function horizontal_anchor() {
  var hash = decodeURIComponent(location.hash); // декодируем специальные символы, такие как пробелы
  var element = document.getElementById(hash.substring(1));
  if (element) {
    var parent = element.closest(".slide");
    let targetTop =
      window.pageYOffset !== undefined
        ? window.pageYOffset
        : (
            document.documentElement ||
            document.body.parentNode ||
            document.body
          ).scrollTop;
    parent.scrollTo({
      left: element.offsetLeft,
      top: targetTop,
      behavior: "smooth"
    });
  }
}

document.addEventListener("DOMContentLoaded", function () {
  // при загрузке
  if (location.hash) horizontal_anchor();
  // при изменении URL
  window.addEventListener("hashchange", function (event) {
    event.preventDefault();
    horizontal_anchor();
    return false;
  });
});

Полный пример в контексте можно найти здесь: https://codepen.io/BernhardWebstudio/pen/eYqmaKO.

В этом примере, когда вы нажимаете на Next или Prev, страница прокручивается так, что изображение оказывается в верхней части окна (iframe), а не остается на месте, вертикально. Кроме того, похоже, что behavior: "smooth" не соблюдается.

Ответ или решение

Чтобы реализовать горизонтальную прокрутку без вертикальной прокрутки при нажатии на ссылки- якоря в вашем слайдере изображений, необходимо внести несколько изменений в ваш JavaScript код. Ваша идея использовать preventDefault() и scrollTo() — это правильный подход, но давайте уточним некоторые моменты, которые помогут вам избежать вертикальной прокрутки и добиться плавного поведения.

Вот детализированный подход, как это сделать:

  1. Отмените действие по умолчанию для ссылок, которые вы используете для навигации по изображениям.
  2. Используйте метод scrollLeft для прокрутки родительского контейнера, вместо того чтобы использовать scrollTo, так как он может вызывать проблемы с поведением.

Вот обновленный код:

function horizontal_anchor() {
  var hash = decodeURIComponent(location.hash); // декодируем специальные символы
  var element = document.getElementById(hash.substring(1));

  if (element) {
    var parent = element.closest(".slide"); // родительский элемент для прокрутки
    let targetTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; // текущее вертикальное положение

    // Прокрутка по горизонтали к элементу
    parent.scrollTo({
      left: element.offsetLeft,
      top: targetTop,
      behavior: "smooth" // плавная прокрутка
    });
  }
}

document.addEventListener("DOMContentLoaded", function () {
  // При загрузке страницы
  if (location.hash) horizontal_anchor();

  // На изменение URL
  window.addEventListener("hashchange", function (event) {
    event.preventDefault(); // отменяем стандартное поведение
    horizontal_anchor(); // вызываем функцию прокрутки
  });
});

// Добавьте обработчики на ваши ссылки для навигации
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
  anchor.addEventListener('click', function(event) {
    event.preventDefault(); // предотвратить переход по якорю
    location.hash = this.getAttribute('href'); // обновление URL без прокрутки
  });
});

Объяснение:

  • preventDefault(): Отключает стандартное поведение ссылки, которое вызывает вертикальную прокрутку.
  • location.hash: Используется для изменения хеша URL, что вызывает событие hashchange, но без фактического вертикального скролла.
  • scrollTo(): Мы вызываем эту функцию для плавной горизонтальной прокрутки. Убедитесь, что ваш CSS настроен так, чтобы scroll-snap-align работал корректно в вашем изображении, это поможет улучшить пользовательский опыт.

Замечания:

  1. Убедитесь, что ваш контейнер (на который вы вызываете scrollTo) имеет свойство overflow-x установленное в auto или scroll, иначе горизонтальная прокрутка не сработает.
  2. Проверьте, что все ваши изображения имеют правильные размеры и настройки для корректной работы flexbox и scroll-snap.

Постоянно тестируйте свою реализацию, чтобы убедиться, что поведение соответствует вашим ожиданиям и работает на разных устройствах.

Оцените материал
Добавить комментарий

Капча загружается...