Восстановление позиции

Smooth Scroll в JavaScript позволяет не только плавно перемещаться по странице, но и управлять положением прокрутки при повторных посещениях или возврате на страницу. Восстановление позиции становится критически важным для SPA (Single Page Application), длинных лендингов и динамических интерфейсов, где пользователь ожидает, что после перехода назад он окажется в том же месте страницы, где остановился.

Хранение позиции прокрутки

Для сохранения текущей позиции используется объект window.scrollY (для вертикальной прокрутки) и window.scrollX (для горизонтальной). Пример:

let scrollPosition = 0;

window.addEventListener('scroll', () => {
    scrollPosition = window.scrollY;
});

Этот подход фиксирует текущую координату прокрутки и позволяет использовать её для последующего восстановления.

Восстановление позиции после навигации

В современных приложениях часто используется History API. При переходе между страницами или состояниями можно сохранить позицию в объекте состояния:

window.history.replaceState({ scrollY: window.scrollY }, '');

При возврате на страницу через popstate:

window.addEventListener('popstate', (event) => {
    if (event.state && typeof event.state.scrollY === 'number') {
        smoothScrollTo(event.state.scrollY);
    }
});

Функция плавного скролла до позиции

Smooth Scroll реализует плавное перемещение к координате, чтобы восстановление позиции выглядело естественно. Минимальная функция:

function smoothScrollTo(y) {
    const start = window.scrollY;
    const change = y - start;
    const duration = 500;
    let currentTime = 0;

    function animateScroll() {
        currentTime += 16; // примерно 60 FPS
        const val = easeInOutQuad(currentTime, start, change, duration);
        window.scrollTo(0, val);
        if (currentTime < duration) {
            requestAnimationFrame(animateScroll);
        }
    }

    animateScroll();
}

// Функция плавного ускорения и замедления
function easeInOutQuad(t, b, c, d) {
    t /= d / 2;
    if (t < 1) return c / 2 * t * t + b;
    t--;
    return -c / 2 * (t * (t - 2) - 1) + b;
}

Сохранение позиции для динамических элементов

Когда контент страницы загружается динамически, координаты элементов могут меняться. В этом случае лучше сохранять позицию не через численные значения scrollY, а через идентификаторы элементов:

window.history.replaceState({ anchor: 'section-3' }, '');

Восстановление позиции выполняется через document.getElementById:

window.addEventListener('popstate', (event) => {
    if (event.state && event.state.anchor) {
        const element = document.getElementById(event.state.anchor);
        if (element) smoothScrollTo(element.offsetTop);
    }
});

Интеграция с Smooth Scroll библиотеками

Современные библиотеки для плавного скролла, такие как smooth-scroll, позволяют упростить восстановление позиции:

const scroll = new SmoothScroll();
window.addEventListener('popstate', (event) => {
    if (event.state && event.state.anchor) {
        const target = document.querySelector(`#${event.state.anchor}`);
        if (target) scroll.animateScroll(target);
    }
});

Здесь используется встроенный метод animateScroll, который учитывает скорость, easing и корректно управляет позиционированием при возврате назад.

Управление прокруткой при AJAX-загрузке

В SPA или страницах с подгрузкой контента через AJAX важно учитывать, что восстановление позиции до загрузки контента может привести к неверному отображению. Решение — отсрочить скролл до полной отрисовки нужного блока:

function restoreScrollPosition(anchor) {
    const checkExist = setInterval(() => {
        const element = document.getElementById(anchor);
        if (element) {
            smoothScrollTo(element.offsetTop);
            clearInterval(checkExist);
        }
    }, 50);
}

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

Обработка разных сценариев возврата

  • Стандартное возвращение браузером: через popstate с сохранением позиции.
  • Перезагрузка страницы: хранение координат в localStorage:
window.addEventListener('beforeunload', () => {
    localStorage.setItem('scrollY', window.scrollY);
});

window.addEventListener('load', () => {
    const savedY = parseInt(localStorage.getItem('scrollY'), 10);
    if (!isNaN(savedY)) smoothScrollTo(savedY);
});
  • Многократное сохранение для разных секций: использование объекта:
let scrollPositions = {};
document.querySelectorAll('section').forEach(section => {
    section.addEventListener('scroll', () => {
        scrollPositions[section.id] = section.scrollTop;
    });
});

Выводы по восстановлению позиции

Восстановление позиции прокрутки в Smooth Scroll требует сочетания:

  • Отслеживания текущих координат (scrollX, scrollY).
  • Сохранения состояния через History API или localStorage.
  • Плавного перемещения с помощью функций easing.
  • Учета динамического контента, чтобы координаты были актуальными.
  • Работы с идентификаторами элементов, когда численные координаты ненадежны.

Такая организация позволяет создавать интерфейсы, где возврат к предыдущему положению страницы будет естественным, удобным и предсказуемым, что особенно важно для длинных и интерактивных страниц.