Implement smooth scrolling in pure Javascript

Smooth scrolling is something very cool, we all like. Most of the time, people add it to their websites via jQuery plugins. Although those plugins are great, they might not be a good fit if your are a guy called Jimmy who doesn’t want to add jQuery to his project. If you are this guy, stay with me, I will show you how to implement smooth scrolling yourself, with vanilla Javascript.

 

It’s all about animations

Smooth scrolling, carousels, games,  and many other dynamic things we see on webpages, are all based on a powerful javascript feature: animations. An animation consists in moving an element from one state to another, by incrementally changing one or many of its properties during a period of time.

start
Starting point
end
Ending point

 

Thinking of smooth scrolling, the animation here will consist in scrolling a webpage from its current scroll position to a target position, by incrementally changing it’s scroll position, during a period of time.
Okay, we now know that smooth scrolling is a kind of animation, what’s next ?

 

Picking an easing function

As I said in the preceding section, to make our page scroll smoothly, we will need to incrementally change it’s scroll position. But the most important thing, is the rate at which that position will change. Does the value speed up initially and then slow down ? Does the value instead start slowly and then speed up? An easing function, is what we use to calculate this rate.

easing
Easing function

Easing functions are based on mathematical equations, and we will cover them in another article.

Now, we need to choose an easing function for implementing our smooth scrolling. Let’s pick the easeInOutQuad function from Robert Penner’s very popular easing functions. You can find them all on Github. The easeInOutQuad function will make our page scrolling fast at the beginning, and then slow as it comes to the target.

//easeInOutQuad
function easing(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;
}

 

Writing the smooth scrolling function

Computing the page current scroll position

var startPosition = window.scrollY || window.pageYOffset;

Both of the window.scrollY and window.pageYOffset properties contain the number of pixels that the webpage is currently scrolled from the top.

Computing the target element position

var targetPosition = target.getBoundingClientRect.top();

Here we assume target is the scroll target element. The getBoundingClientRect  method called on an element, returns a  DOMRect object, which contains the left, top, right, bottom, x, y, width, height properties describing the border-box in pixels; the top property is the one we need here.

Computing the distance between the page current scroll position and the target element position

var distance  = targetPosition - startPosition;

Putting the blocks together

/*
* target is the element we want to scroll to
* duration is the scroll delay in ms
*/

function smoothScroll (target, duration) {
  var startPosition = window.scrollY || window.pageYOffset;
  var targetPosition = target.getBoundingClientRect.top();
  var distance = targetPosition - startPosition;
  var timeStart = null;

  function loop(timeCurrent) {
    if(timeStart === null) timeStart = timeCurrent;
    
    timeElapsed = timeCurrent - timeStart;

    next = easing(timeElapsed, startPosition, distance, duration);

    // Vertically scroll from the current scroll position to next
    window.scrollTo(0, next);

    // Rerun the animation until the delay(duration) expires.
    if(timeElapsed < duration) window.requestAnimationFrame(loop);
  }

  // Our good old easeInOutQuad function
  function easing(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;
  }
 
  // Start running the animation
  window.requestAnimationFrame(loop);
}

The window.requestAnimationFrame() method tells the browser that we are going to perform an animation. It takes a callback method (loop) that will run on each update. We keep running the animation until the scrolling delay(duration) has expired.

Each time it’s called, the loop function receives as a default argument, the current timestamp.  Thanks to our easing method, we are able to calculate the next position to scroll to. Then, we use the window.scrollTo() method to incrementally scroll.

Binding the click event on links to the smoothScroll function

document.querySelector('a').onclick = function(event) {
  smoothScroll(event.target, 1000); // scroll delay here will be 1s
}

That’s it ! We have just implemented our own smooth scrolling function in pure javascript.

Thanks for Reading !

 

One thought on “Implement smooth scrolling in pure Javascript

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s