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

Сделать это проще-простого. Вверху мы делаем меню, которое может выглядеть как-то так.

<ul class="menu">
    <li><a href="#part1">раздел 1</a></li>
    <li><a href="#part2">раздел 2</a></li>
    <li><a href="#part3">раздел 3</a></li>
    <li><a href="#part4">раздел 4</a></li>
    <li><a href="#part5">раздел 5</a></li>
</ul>

А на каждую секцию добавляем якорную ссылку, которая выглядит так:

<a id="part1"></a>

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

Как уже понял догадливый читатель, для этого на сайт придётся добавить щепотку JavaScript. Сделать это можно разными способами. Я покажу сначала способ курильщика, а потом два способа здоровых человеков.

1 С помощью плагинов

Что делает современный веб-мастер, когда перед ним стоит какая-то задача? Правильно, идёт в гугл/яндекс, а оттуда на stackoverflow. Что ему обычно советуют на stackoverflow? Правильно, сходить на git и выкачать оттуда нужный плагин, который давным-давно был кем-то разработан для решения именно таких задач.

Для плавного скроллинга плагинов существует целая охапка, но я лично одно время использовал SmoothScroll, который живёт вот здесь. Устанавливается он так.

Во-первых, нужен jQuery. Если ещё не используете его для своего проекта, то подключаете в подвале или в шапке. Выглядеть всё это будет как-то так (подразумевается, что все JavaScript файлы вы складываете в папочку js):

<script src="js/jquery-3.4.1.min.js"></script>

Во-вторых, скачиваете и подключаете сам плагин, ниже jQuery. Вам нужен только один файл.

<script src="js/smooth-scroll.js"></script>

И третье – прописываете вот такой код:

<script>
$(document).ready(function() {
    var scroll = new SmoothScroll('a[href*="#"]', {
        speed: 800,
        easing: 'easeInOutQuad'
    });
});
</script>

Два параметра отвечают за скорость скроллинга (в миллисекундах) и кривую анимации. В данном случае будет график с медленным стартом, ускорением и быстрым финишем.

Этого достаточно для работы.

Важно! Якорные ссылки должны быть с селектором id. Селектор name, который тоже иногда используют в таких случаях, плагин не найдёт.

2 С помощью jQuery

Если у вас уже подключен в проект jQuery, то можете не скачивать никакой плагин, а просто прописать вот такой код.

<script>
$('.menu li').on('click', 'a', function (event) {
    event.preventDefault();
    var id = $(this).attr('href'),
    top = $(id).offset().top;
    $('body, html').animate({scrollTop: top}, 800);
});
</script>

Всё. Цифра, как вы догадались, скорость прокрутки.

3 На чистом JavaScript

Если вы не любите jQuery, то можете добавить скроллинг на чистом JS. Выглядит это так. Каждой секции присваиваете класс section-start и вставляете вот такой код:

<script>
const scrollToElements = document.querySelectorAll(".menu li a");
const sectionsArray = Array.from(document.querySelectorAll("section-start"));
scrollToElements.forEach(function (el) {
    el.addEventListener('click', function (e) {
        e.preventDefault();
        var targetId = el.getAttribute('href');
        var target = document.querySelector(targetId);
        if (target) {
            sectionsArray.forEach(function (section, index) {
                if (section.id === targetId.replace('#', '')) {
                    currentSectionIndex = index;
                }
            });
            target.scrollIntoView({ behavior: 'smooth' });
        }
    });
});
</script>

Как видите, всё просто. Мы делаем массив элементов меню и коллекцию секций, причём они соответствуют друг другу по порядку. На каждый элемент меню вешаем метод scrollIntoView. Если нужно больше настроек — добро пожаловать в документацию по этому методу. Небольшая вишенка на торте — можно не использовать никакие внутренние ссылки, повесив события на те элементы, которые вам удобнее.

Код использует синтаксис ES6, так что в старых браузерах работать не будет. Впрочем, для того, чтобы сделать ему «даунгрейд», можно прекрасно обойтись без всякого Babel и полифилов. Достаточно заменить const на var, а forEach на обычный цикл for. Что же касается scrollIntoView, то он прекрасно совместим со всеми основными браузерами, включая EDGE и IE9.

Заключение

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

P.S. Дункана Маклауда я вставил просто для красоты, потому что не смог придумать интересную картинку на тему «скролл сайта».

Посмотреть код в «естественной среде обитания» и поиграться с ним можно здесь.