Smooth scrolling when clicking an anchor link

The new hotness in CSS3. This is a lot easier than every method listed on this page and requires no Javascript. Just enter the below code into you css and all of a sudden links point to locations inside you own page will have a smooth scrolling animation.

html{scroll-behavior:smooth}

After that any links pointed towards a div will smoothly glide over to those sections.

<a href="#section">Section1</a>

Edit: For those confused about the above a tag. Basically it's a link that's clickable. You can then have another div tag somewhere in your web page like

<div id="section">content</div>

In this regard the a link will be clickable and will go to whatever #section is, in this case it's our div we called section.

BTW, I spent hours trying to get this to work. Found the solution in some obscure comments section. It was buggy and wouldn't work in some tags. Didn't work in the body. It finally worked when I put it in html{} in the CSS file.


Update April 2018: There's now a native way to do this:

document.querySelectorAll('a[href^="#"]').forEach(anchor => {
    anchor.addEventListener('click', function (e) {
        e.preventDefault();

        document.querySelector(this.getAttribute('href')).scrollIntoView({
            behavior: 'smooth'
        });
    });
});

This is currently only supported in the most bleeding edge browsers.


For older browser support, you can use this jQuery technique:

$(document).on('click', 'a[href^="#"]', function (event) {
    event.preventDefault();

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top
    }, 500);
});

And here's the fiddle: http://jsfiddle.net/9SDLw/


If your target element does not have an ID, and you're linking to it by its name, use this:

$('a[href^="#"]').click(function () {
    $('html, body').animate({
        scrollTop: $('[name="' + $.attr(this, 'href').substr(1) + '"]').offset().top
    }, 500);

    return false;
});

For increased performance, you should cache that $('html, body') selector, so that it doesn't run every single time an anchor is clicked:

var $root = $('html, body');

$('a[href^="#"]').click(function () {
    $root.animate({
        scrollTop: $( $.attr(this, 'href') ).offset().top
    }, 500);

    return false;
});

If you want the URL to be updated, do it within the animate callback:

var $root = $('html, body');

$('a[href^="#"]').click(function() {
    var href = $.attr(this, 'href');

    $root.animate({
        scrollTop: $(href).offset().top
    }, 500, function () {
        window.location.hash = href;
    });

    return false;
});

The correct syntax is:

//Smooth scrolling with links
$('a[href^=\\#]').on('click', function(event){     
    event.preventDefault();
    $('html,body').animate({scrollTop:$(this.hash).offset().top}, 500);
});

// Smooth scrolling when the document is loaded and ready
$(document).ready(function(){
  $('html,body').animate({scrollTop:$(location.hash).offset().‌​top}, 500);
});

Simplifying: DRY

function smoothScrollingTo(target){
  $('html,body').animate({scrollTop:$(target).offset().​top}, 500);
}
$('a[href^=\\#]').on('click', function(event){     
    event.preventDefault();
    smoothScrollingTo(this.hash);
});
$(document).ready(function(){
  smoothScrollingTo(location.hash);
});

Explanation of href^=\\#:

  • ^ means it matches what contains # char. Thus only match anchors to make sure it's a link for the same page (Thanks Peter Wong for your suggestion).
  • \\ is because the # is a special char in css selector, so we have to escape it.