[javascript] Smooth scrolling when clicking an anchor link


The correct syntax is:

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

// Smooth scrolling when the document is loaded and ready
  $('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){     

Explanation of href*=\\#:

  • * means it matches what contains # char. Thus only match anchors. For more about the meaning of this, see here
  • \\ is because the # is a special char in css selector, so we have to escape it.

I have a couple of hyperlinks on my page. A FAQ that users will read when they visit my help section.

Using Anchor links, I can make the page scroll towards the anchor and guide the users there.

Is there a way to make that scrolling smooth?

But notice that he's using a custom JavaScript library. Maybe jQuery offers somethings like this baked in?

Never forget that offset() function is giving your element's position to document. So when you need scroll your element relative to its parent you should use this;

     scrollTop: $( $.attr(this, 'href') ).position().top + $('.scroll-div').scrollTop()
     }, 500);       

The key point is getting scrollTop of scroll-div and add it to scrollTop. If you won't do that position() function always gives you different position values.

Here is the solution I implemented for multiple links and anchors, for a smooth scroll:

http://www.adriantomic.se/development/jquery-localscroll-tutorial/ if you have your navigation links set up in a navigation div and declared with this structure:

<a href = "#destinationA">

and your corresponding anchor tag destinations as so:

<a id = "destinationA">

Then just load this into the head of the document:

    <!-- Load jQuery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>

<!-- Load ScrollTo -->
<script src="http://flesler-plugins.googlecode.com/files/jquery.scrollTo-1.4.2-min.js"></script>

<!-- Load LocalScroll -->
<script src="http://flesler-plugins.googlecode.com/files/jquery.localscroll-1.2.7-min.js"></script>

<script type = "text/javascript">
        // Scroll the whole document

Thanks to @Adriantomic

The answer given works but disables outgoing links. Below a version with an added bonus ease out (swing) and respects outgoing links.

$(document).ready(function () {
    $('a[href^="#"]').on('click', function (e) {

        var target = this.hash;
        var $target = $(target);

        $('html, body').stop().animate({
            'scrollTop': $target.offset().top
        }, 900, 'swing', function () {
            window.location.hash = target;

This solution will also work for the following URLs, without breaking anchor links to different pages.




var $root = $('html, body');
$('a').on('click', function(event){
    var hash = this.hash;
    // Is the anchor on the same page?
    if (hash && this.href.slice(0, -hash.length-1) == location.href.slice(0, -location.hash.length-1)) {
            scrollTop: $(hash).offset().top
        }, 'normal', function() {
            location.hash = hash;
        return false;

I haven't tested this in all browsers, yet.

Modern browsers are a little faster these days. A setInterval might work. This function work well in Chrome and Firefox these days.(A little slow in safari, didn't bother with IE)

function smoothScroll(event) {
    if (event.target.hash !== '') { //Check if tag is an anchor
        const hash = event.target.hash.replace("#", "")
        const link = document.getElementsByName(hash) 
        //Find the where you want to scroll
        const position = link[0].getBoundingClientRect().y 
        let top = 0

        let smooth = setInterval(() => {
            let leftover = position - top
            if (top === position) {

            else if(position > top && leftover < 10) {
                top += leftover
                window.scrollTo(0, top)

            else if(position > (top - 10)) {
                top += 10
                window.scrollTo(0, top)

        }, 6)//6 milliseconds is the faster chrome runs setInterval

Tested and Verified Code

// Add smooth scrolling to all links
jQuery("a").on('click', function(event) {

// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
  // Prevent default anchor click behavior

  // Store hash
  var hash = this.hash;

  // Using jQuery's animate() method to add smooth page scroll
  // The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
  jQuery('html, body').animate({
    scrollTop: jQuery(hash).offset().top
  }, 800, function(){

    // Add hash (#) to URL when done scrolling (default click behavior)
    window.location.hash = hash;
} // End if

Using JQuery:

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

jQuery is the best!

    //code here

I suggest you to make this generic code :


var the_id = $(this).attr("href");

    $('html, body').animate({
    }, 'slow');

return false;});

You can see a very good article here : jquery-effet-smooth-scroll-defilement-fluide