Плавная прокрутка к якорям

14.09.19

Очень часто на лендингах или просто на длинных страничках можно встретить плавную прокрутку к якорям.

Разметка блока навигации имеет примерно такой вид:

<ul class="nav-block">
  <li><a href="#firstBlock">First block</a></li>
  <li><a href="#secondBlock">Second block</a></li>
  <li><a href="#thirdBlock">Third block</a></li>
  <li><a href="#fourthBlock">Fourth block</a></li>
</ul>

Для обозначения якоря будем использовать атрибут id. Например:

<a id="firstBlock"></a>

Сначала напишем скрипт с помощью jQuery

$('.nav-block').on('click','a', function(e) {
    e.preventDefault();
    var id  = $(this).attr('href'),
        top = $(id).offset().top;
    $('body,html').stop().animate({scrollTop: top}, 1500);
});

1500 - время прокрутки в миллисекундах

На нативном JavaScript код выглядит чуть сложнее

function elmYPosition(eID) {
    var elm = document.getElementById(eID);
    var y = elm.offsetTop;
    var node = elm;
    while (node.offsetParent && node.offsetParent != document.body) {
        node = node.offsetParent;
        y += node.offsetTop;
    } return y;
}

function smoothScroll(eID) {
    var startY = self.pageYOffset;
    var stopY = elmYPosition(eID);
    var distance = stopY > startY ? stopY - startY : startY - stopY;
    if (distance < 100) {
        scrollTo(0, stopY); return;
    }
    var speed = Math.round(distance / 100);
    if (speed >= 20) speed = 20;
    var step = Math.round(distance / 25);
    var leapY = stopY > startY ? startY + step : startY - step;
    var timer = 0;
    if (stopY > startY) {
        for ( var i=startY; i<stopY; i+=step ) {
            setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
            leapY += step; if (leapY > stopY) leapY = stopY; timer++;
        } return;
    }
    for ( var i=startY; i>stopY; i-=step ) {
        setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
        leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
    }
}
blog comments powered by Disqus