Is it possible to animate scrollTop with jQuery?

I want to smoothly scroll down. I do not want to have to write a function for that - especially if jQuery already has one.


Solution 1:

You can just use .animate() the scrollTop property, like this:

$("html, body").animate({ scrollTop: "300px" });

Solution 2:

Nick's answer works great. Be careful when specifying a complete() function inside the animate() call because it will get executed twice since you have two selectors declared (html and body).

$("html, body").animate(
    { scrollTop: "300px" },
    {
        complete : function(){
            alert('this alert will popup twice');
        }
    }
);

Here's how you can avoid the double callback.

var completeCalled = false;
$("html, body").animate(
    { scrollTop: "300px" },
    {
        complete : function(){
            if(!completeCalled){
                completeCalled = true;
                alert('this alert will popup once');
            }
        }
    }
);

Solution 3:

Nick's answer works great and the default settings are nice, but you can more fully control the scrolling by completing all of the optional settings.

here is what it looks like in the API:

.animate( properties [, duration] [, easing] [, complete] )

so you could do something like this:

.animate( 
    {scrollTop:'300px'},
    300,
    swing,
    function(){ 
       alert(animation complete! - your custom code here!); 
       } 
    )

here is the jQuery .animate function api page: http://api.jquery.com/animate/

Solution 4:

Like Kita mentioned there is a problem with multiple callbacks firing when you animate on both 'html' and 'body'. Instead of animating both and blocking subsequent callbacks I prefer to use some basic feature detection and only animate the scrollTop property of a single object.

The accepted answer on this other thread gives some insight as to which object's scrollTop property we should try to animate: pageYOffset Scrolling and Animation in IE8

// UPDATE: don't use this... see below
// only use 'body' for IE8 and below
var scrollTopElement = (window.pageYOffset != null) ? 'html' : 'body';

// only animate on one element so our callback only fires once!
$(scrollTopElement).animate({ 
        scrollTop: '400px' // vertical position on the page
    },
    500, // the duration of the animation 
    function() {       
        // callback goes here...
    })
});

UPDATE - - -

The above attempt at feature detection fails. Seems like there's not a one-line way of doing it as webkit type browsers pageYOffset property always returns zero when there's a doctype. Instead, I found a way to use a promise to do a single callback for every time the animation executes.

$('html, body')
    .animate({ scrollTop: 100 })
    .promise()
    .then(function(){
        // callback code here
    })
});