How to animate scroll in jQuery

  • by Tyler (236)
  • Time to complete: 5 minutes

In this guide, I'll provide sample code for animating scroll in jQuery, and for those looking for more I'll break down each component.

1

Assume we have a simple button at the bottom of our page that when clicked scrolls the user to the top of the page.



The markup is simple. Here's the JavaScript.


$(function() { $("#top").on('click', function() { $("HTML, BODY").animate({ scrollTop: 0 }, 1000); }); });


Note that the first line, $(function() { is shorthand for $(document).ready(function() {. This simply means we are passing a callback function to the document ready event. It's necessary to do this when our code is expecting DOM elements to exist. Next we are creating a click event handler for our button, $("#top").on('click', function() {. First we specify which element we are listening to, which in our case is #top. The on('click' is very readable - simple means when the user clicks on the #top element. And as before, the anonymous function we create is being passing in as a callback function. So whenever the user clicks on the #top element this function will get fired. Now for the animation. First it should be noted that we are targeting both HTML and BODY for browser compatibility. Some browsers scroll by settings scrollTop on BODY and other on HTML. No, I don't know which ones, and it will probably be unnecessary soon if it isn't already. jQuery provides an animate function that takes a dictionary of CSS properties and values as the first parameter, and an integer representing the animation duration in milliseconds as the second parameter. In our case we are passing in only one css property: scrollTop. And since we are scrolling to the top, we'll set scrollTop to 0. Then as the second parameter we're setting the duration to 1000 milliseconds or if you're really good at math: 1 second. This should give us plenty of time to watch our animation.

2

Now suppose we have an element on the page and we want to scroll to the top of it.



We first need to find out the offset of the image.


var position = $("#image").offset().top;


jQuery's offset() function returns an object containing properties top and left. We're only interested in top because we want to scroll to the top of this element. So using what we've already learned about scroll, we can use our new position as the value of scrollTop:


$(function() { $("#top").on('click', function() { var position = $("#image").offset().top; $("HTML, BODY").animate({ scrollTop: position }, 1000); }); });


This will scroll you to the top of the element with the animation lasting 1 second.

3

Since scrollTop is the position on the page that should land at the top of the window, scrolling to the bottom of the page requires a little bit of math. The position we want to know is the document height - window height. document height will give us the height of the entire web page, while window height just gives us the height of the scrollable area.


var bottom = $(document).height() - $(window).height();


Now we can just use this value in our animation.


$(function() { $("#top").on('click', function() { var bottom = $(document).height() - $(window).height(); $("HTML, BODY").animate({ scrollTop: bottom }, 1000); }); });


4

If you've been experimenting with animating scroll, you've probably noticed that if the scroll distance is small it scrolls very slowly and if the scroll distance is large is scrolls more quickly. This is because we are specifying a duration for the animation, and it doesn't care about distance. In most cases, when your scroll distance can vary you'll want to normalize the scroll rate. So instead of always passing in 1000 for the duration, we want to take our scroll distance into account. First, we have to decide the rate we want to scroll. Let's pick something easy - 1000px/500ms or 1000px/0.5s. We need to write a function that takes the target scroll position, that is the position we are scrolling to, and returns the new duration in milliseconds.


function getDuration(target) { var currentTop = $(window).scrollTop(), rate = 0.5, // 1000px/500ms distance; distance = Math.abs(currentTop - target); return distance * rate; }


First we set our variables. We need to get our current scrollTop position and store that value as currentTop. This allows us to properly calculate the distance between our current position and the target position. Then we specify our rate, which in our case is 0.5 or 1000px/500ms. Finally, we declare our distance variable which will be set soon. Calculating the distance is as simple as subtracting the target from the currentTop. We need to take the absolute value of the result to ensure this works for both directions. Finally we return the new distance we calculated multiplied by the rate. Now let's put our function to use in an example that scrolls us to the bottom of the page at our newly calculated rate.


$(function() { $("#top").on('click', function() { var bottom = $(document).height() - $(window).height(); var duration = getDuration(bottom); $("HTML, BODY").animate({ scrollTop: bottom }, duration); }); });


As you can see the only changes are calling the getDuration function and using the newly calculated duration as the second parameter of the animate function. This method is beneficial because if all of your scrolls will animate at the same speed. If you want to change the speed, all you have to do is modify the rate in our getDuration function. Adjusting the rate to 0.2 will make it go much faster, whereas changing it to 1.5 will slow it down significantly.