PSD to HTML conversion PSD to HTML conversion PSD2HTML.com with over 300 professionals takes the designs to HTML and beyond

Code Snippet

Home » Code Snippets » jQuery » Smooth Scrolling

Smooth Scrolling

Performs a smooth page scroll to an anchor on the same page.

$(document).ready(function() {
  function filterPath(string) {
  return string
    .replace(/^\//,'')
    .replace(/(index|default).[a-zA-Z]{3,4}$/,'')
    .replace(/\/$/,'');
  }
  var locationPath = filterPath(location.pathname);
  var scrollElem = scrollableElement('html', 'body');

  $('a[href*=#]').each(function() {
    var thisPath = filterPath(this.pathname) || locationPath;
    if (  locationPath == thisPath
    && (location.hostname == this.hostname || !this.hostname)
    && this.hash.replace(/#/,'') ) {
      var $target = $(this.hash), target = this.hash;
      if (target) {
        var targetOffset = $target.offset().top;
        $(this).click(function(event) {
          event.preventDefault();
          $(scrollElem).animate({scrollTop: targetOffset}, 400, function() {
            location.hash = target;
          });
        });
      }
    }
  });

  // use the first element that is "scrollable"
  function scrollableElement(els) {
    for (var i = 0, argLength = arguments.length; i <argLength; i++) {
      var el = arguments[i],
          $scrollElement = $(el);
      if ($scrollElement.scrollTop()> 0) {
        return el;
      } else {
        $scrollElement.scrollTop(1);
        var isScrollable = $scrollElement.scrollTop()> 0;
        $scrollElement.scrollTop(0);
        if (isScrollable) {
          return el;
        }
      }
    }
    return [];
  }

});

View Demo

Reference URL

Subscribe to The Thread

  1. Nick says:

    Hi,

    I cant get this to work. Could you provide the appropiate HTML to go with this Javascript?

    Its not obviously clear whats needed, as I’ve tried all sorts of combinations of name values and such.

    Any help would be appreciated

    :)

  2. Jarrett says:

    I LOVE U!!!! i been tryna find how to do this for months! :-)

  3. Dyllon says:

    works like a charm.. thanks so much.

  4. Patricia says:

    Thank you so much for this script. Took me awhile, but I got it to work!

  5. Cole says:

    The Reference URL is now showing a 404 page. Know anywhere else that has the HTML to go along with the JS? …and preferably in english? :)

  6. Andy says:

    great code, one question,

    I have a sidebar widget for my video, archive and tags this code is interfering with. What is the coding/marker to disable this from happening?

  7. Jon says:

    I cannot get this to work for the life of me, I’m following the example perfectly though… Anyone have any ideas?

    • Without a description of your problem, or a URL, no one will ever be able to help.

      One thing I can say is that make sure you are loading the jquery library.

  8. It’s not working on IE8 at my website, I think there is some kind of Bug…
    Could you see it here with IE8? Thank’s

  9. Az says:

    Does this work with Left & Right too?
    Just change “top” to “left” ?

  10. William says:

    Sweet! Thank you

  11. jamie says:

    I got the second method working on my site, but I also tried to get the nav container to follow the page by adding it it the code like this

    $(‘html,body,#nav’)

    So I just added #nav to the selectors here. But it don’t work. The page still scrolls, but the nav container doesn’t follow. Any ideas?

  12. catchatpas says:

    Work perfectly

  13. Fumie says:

    Hi Chris, this is awesome! Very simple and clean and works really good.

    I was wondering if it is possible to get the hash link in the current URL of the browser window (i.e. http://www.example.com#target3) while keeping the smooth scrolling effect, so the each hash link can be bookmarkable.

    Thanks!

  14. I have slightly altered this scroll down to the page onload? My idea here is in PHP to check the refer and only scroll down the page only if they have clicked a link from the domain. At the moment I have

    $referer = $_SERVER['HTTP_REFERER'];
    
    if ($referer != "") {
    	$this->data['scrollTo'] = true;
    }

    website

  15. Jon Green says:

    Thanks for this Chris! I was trying to do this with Jquery.LocalScroll, this is so much easier!! Saved me a huge headache, thanks.

  16. James says:

    i have a div with width: 100% height: 100% and another div left: 100% width: 100% so the body is 200%, how can i make the scroll move horizontally?

  17. Shaun says:

    I changed some bits, which you didn’t explain.. like you expect there to be a corrsponding element id an ID the same as the a.href.. so I changed this

    var target = $(this).attr(“href”);
    To
    var target = $(this).attr(“href”).replace(‘#’,”);

    and this
    scrollTop: $(target).offset().top

    To

    scrollTop: $(‘a[name='+target+']‘).offset().top

    PS. Keep up the good work.

  18. Mike says:

    Hello,

    I’m trying to get this to work but for the life of me cant. As far as I am aware, I’ve check the reference and copied exactly… Any help appreciated.

    http://www.certohost.com/tutorials.php

    Thanks.

  19. pauline says:

    Hi,

    I used technique #2 and it seems to only work when I click on about, the work and contact link doesn’t seem to work and I don’t know why.

    thanks

  20. Awesome, works brilliantly. Barely having to do anything. Thanks Chris

  21. Superb, worked like a charm.
    Thanks!

  22. Richard says:

    Hello..

    Just wondering if you had checked this in Opera… getting some funny results when running some tests… v.nice never the less.

  23. Jon says:

    Hi Chris and co.

    When I use this method #2, my Firefox Developer Toolbar shows a js error as follows:

    Expected identifier or string value in attribute selector but found “#”.

    What am I missing..?

    To help, I am using jquery-1.4.2.min.js, and I’m linking to h2′s with id’s, like so:

    Go to 01
    This is Link 01

    Thanks in advance.

  24. Jon says:

    Sorry, forgot to wrap my code:

    <a href="#link-01">Go to 01</a>
    <h2 id="link-01">This is link number 01</h2>

    Thanks
    Jon

  25. Jack says:

    works like a charm! thanks a bunch!

  26. Thanks Chris.
    This worked perfectly in Firefox and Safari, but not in Opera. I have yet to test out IE. Any fix ideas for Opera. It currently jumps to the #tag, no scroll.

    Any know issues and or fixes for IE?

    FYI, I used technique #2.

  27. Scott says:

    Thanks for the post, i’ve been trying to get something like this working for ages. Any ideas how to alter the scrolling speed?

  28. i used to grab the local scroll for this function. yours works as good. thank you.

  29. weremoose says:

    This seems clean and easy!

    I see other people asked as well before.
    I am also trying to find a solution for a horizontal site I am working on.
    Could this be modified to work in that case?
    Any hints would be extremely helpful…

    • weremoose says:

      Ok… thankfully that didn’t take too much to figure out.
      Using the second method I used this code and it worked:

      $(function(){
          $('a[href*=#]').click(function() {
          if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'')
              && location.hostname == this.hostname) {
                  var $target = $(this.hash);
                  $target = $target.length && $target || $('[name=' + this.hash.slice(1) +']');
                  if ($target.length) {
                      var targetOffset = $target.offset().left;
                      $('html,body').animate({scrollLeft: targetOffset}, 1000);
                      return false;
                  }
              }
          });
      });
    • Cozza says:

      Thanks for this!

  30. Keven says:

    I’ve been testing a bunch of different code for smooth scrolling over the last couple of days and these seem to be the most straight forward and easy to implement. I’m a designer not a coder so the simpler the better. Awesome stuff.

    Just one issue. I noticed Fumie asked about having the hash link appear in the URL and Michal Kopanski pointed out that technique #1 let’s you keep the hash links, while technique #2 does not.

    The problem I’m having with #1 is that I can’t link to the hash links from a different page (e.g. from the home page there’s a link something like “about#sometag”). Is there a way to have the hash links appear using technique #2?

  31. Davide says:

    I have external anchor links on my page that doesn’t work anymore when using the script :-(

  32. Chris Coyer for President!

  33. mre says:

    If you want to prevent that the animations “queue up” replace this line:
    $('html,body').animate({
    with this:
    $('html,body').stop().animate({

  34. alex says:

    Yay!!!
    Thank you sooooo much, my website is 10x better looking now and your code was so easy to use!
    xo

  35. Jez says:

    This is great but it dont want the top to be the top of the browser….

    I have a fixed header at the top and i want the point it scrolls to, to be the bottom of the header.

    Regardless what i do it will always scroll the anchor to the very top of the browser :(

    Anyway of achieving this?

  36. Hi all,

    just thought I’d point out that script 1 may cause you problems if you are linking to # anchors on other pages than the one you are on.

    If the link were on the same page then the jQuery works fine.

    If any one knows of a solution for enabling # links to other pages, that would be great !
    Thanks

  37. Pieter says:

    Thank you for the script. I just have one question: Why would you not use the anchor text in the URL? Has it any benefits? In my eyes it just makes the user experience less. It feels like working in flash. :)

  38. Chris Beard says:

    We use a content management system that sometimes requires anchors within links to other pages. I’d love to be able to switch the choice off but I’m afraid we’re stuck with it !
    Alas, the above two scripts won’t work for links such as this:

    http://www.mysite.com/otherpage.html#someanchor

  39. The first method seemed a bit laborious with the separated function, so I integrated it into the bind command as a callback function. Seems to work perfectly fine, though I’ve only tested it in Chrome and IE7.

    $(document).ready(function() {
       $('a[href*=#]').bind('click', function(e) {
    	e.preventDefault(); //prevent the "normal" behaviour which would be a "hard" jump
    
    	var target = $(this).attr("href"); //Get the target
    
    	// perform animated scrolling by getting top-position of target-element and set it as scroll target
    	$('html, body').stop().animate({ scrollTop: $(target).offset().top }, 2000, function() {
    	     location.hash = target;  //attach the hash (#jumptarget) to the pageurl
    	});
    
    	return false;
       });
    });
  40. Ichi says:

    Many thanks, It was very useful, easy to use and works fine… also thanks to all comments I could improve it to fit it to my web…

  41. darma says:

    hello and thank you for the nice bit of code,
    i tried technique#1 and it’s well done to update the location as the animation is completed, but the browser back-next buttons act a little strange, it looks as the history is kind of “shifted” by one “event” (all in FF 3.6.10, chrome 7.0.517.44 and IE7 PC) : first hit the back button and nothing happens on the screen but the hash goes back well in the URL field, second time the hash goes back again and the screen now starts to show its previous state but then they’re not matching.
    hmm not sure i’m clearly explaining, anyone understanding my point?
    anyone who got to fix this?
    thanks!

    • I’ve gotten rid of Technique #1 and Technique #2 and presented just a single best-of way to do this. As is, the “back button” in the browser does not work. That is a little outside of the scope of this already pretty bulky “snippet”.

      If you are interested in having the back button work, I’d mess with http://www.asual.com/jquery/address/ and basically use the address change function they provide to trigger a click on the appropriate link when it changes, so back-button-scrolling will work.

  42. Been coming to your site for ages and only just now found the snippets section (duh on my behalf)… they are brilliant!

    One question about this one… is it possible to add easing in to this?

    Thanks mate, Sam

  43. Chris says:

    Hi,

    I would also love to know how to add easing?

    Thanks Chris

  44. dynamicflow says:

    hey thanx this code helped us a lot

  45. Chris, thanks a lot! I was messing around with different jQuery plugins and I couldn’t get both (scrolling and enabling back-button/bookmarking) to work at the same time. This just works!

  46. All previous examples require anchors to have id as well as name.
    This does not, and skips animation if it cannot find anchor link:

    $(document).ready(function() {
    $('a[href*=#]').bind('click', function(e) {
    var target = $(this).attr("href");
    var position = $('a[name*='+target.replace('#','')+']').offset().top;
    if(position!=0){
    //prevent the "normal" behaviour which would be a "hard" jump
    e.preventDefault();
    // perform animated scrolling by getting top-position of target-element and set it as scroll target
    $('html, body').animate({ scrollTop: position }, 500, function() {
    location.hash = target; //attach the hash (#jumptarget) to the pageurl
    });
    return false;
    }
    });
    });

  47. Tim Martin says:

    Fantastic script, Chris. It does however cause some conflict when using other effects on the same page (take Lightbox for example). Keep up the good work!

  48. Rubira says:

    jQuery(document).ready(function() {

    var scrollWin = function (selector) {
    jQuery('html, body').animate({
    scrollTop: jQuery(selector).offset().top
    }, 800);
    }

    jQuery("[href^=#]").click(function(e) {
    scrollWin (jQuery(this).attr("href"));
    return false;
    });

    });

  49. Bryan says:

    I have been experimenting with the script and it is working well, mostly. When I create a “back to top” link referring to an id in the body tag it stops just a few pixels short of the very top — it scrolls (smoothly!) up to maybe 10px short of the very top. Why is this? Thanks.

    • Bryan says:

      One other thing. Maybe I missed a solution in the above comments, but the script above does not seem to work in internet explorer. Is there some way to make it scroll smoothly in ie? Thank you.

  50. Sascha Martin says:

    Chris,

    thank you for your awesome tutorials and scripts.

    This one worked for me fine and made the side behave beautifully.

    I only discovered, that it doesn’t work inside my select box:

    <form name="example_form">
    <select name="example_select" onchange="document.location.hash=this.value">
    <option value='anchor1'>target1</option>
    <option value='anchor2'>target2</option>
    </select></form>

    Do you have any idea for me?

    Thank you in advance!!

    Keep on with your great work,
    Sascha from Germany

  51. Srirangan says:

    Great blog post. Code “just works”!

    Thanks for posting..

    - Sri

  52. Scott says:

    Hello everyone,

    I wonder if someone has any ideas about the error that i am receiving in the console:

    $target.offset() is null
    var targetOffset = $target.offset().top;

    I can get the page to scroll down to the correct sections smoothly, but once i click the back to top link, it jumps to the top of the page.

    If anyone has any suggestions to try then please let me know, as it is driving a little bit crazy now :S

    Thanks for any help.

  53. Aaron says:

    Im battling with this a bit too…

    I cant get the ‘back to top’ aspect to work in FF….And Fire Bug spits out the following error:

    $target.offset() is null
    Line 29

    The other aspects of functionality work great…although like Scott above this post, it animates once, then snaps after that to whichever link…..

    Any help at all, or suggestions would be greatly appreciated…

    URL for refence: http://varsitypixels.com

    Thanks in advance!

    • Jamie says:

      I was getting this error too. Its was happening because i didnt have the anchor id in place. i.e.

  54. edward says:

    Hey guys, loving this awesome code, but I’m having trouble implementing it into my website.

    I’m sort of a cut/paste beginner at this, I got it working at first, but then after adding some other snippets it doesn’t seem to work.

    Specifically, i’m having trouble with the “back to top” links.
    The first one works, but the links farther down on the page don’t.

    http://www.ed-yu.com/website

    Thanks for any insight!

  55. Lewis says:

    To add easing – link to the jquery easing 1.3 pack

    Then substitute the section below

    // Animate to target
    $(scrollElem).animate({scrollTop: targetOffset}, 800, ‘easeInOutExpo’, function() {

  56. Lewis says:

    Great script by the way – thanks for sharing!

  57. Love the code! I made a couple changes someone might find use for –

    Using the code in the demo gave a syntax error on FF 4 when it encountered a nonexistant target – the variable target in if (target) { is missing its $ in front.
    Also, replacing
    var $target = $(this.hash), target = this.hash;
    with
    var $target = jQuery("a[name=" + this.hash.substr(1) + "]");
    makes it compatible with existing HTML hashtags.

  58. Brian says:

    This works great! Love it!
    Just a quick question: How can I make it scroll up to a certain height, i.e. 50px from the top?

    Thanks!

  59. TPa says:

    Thanks! Did exactly what I wanted and wasn’t bloated with pointless features.

  60. Caroline says:

    Any plans to post this on Github? :D (pretty puleeeeez!)

  61. Brad says:

    Great script! But its not working on ipad/iphone. Does anyone know any fixes to this?
    Thanks!

  62. Andy says:

    Love this script, but I also have the issue above. Not working on ipad/iphone. Any fix for this please?

  63. retinafunk says:

    It did not work on ios safari (iphone,ipod,ipad) form me too, but this shorter code did work everywhere ..and does the same (without showing the hash in URL , but I will fix that).
    I leave it to the jquery experts to find out why…

    $(function(){

    $(‘a[href*=#]‘).click(function() {

    if (location.pathname.replace(/^\//,”) == this.pathname.replace(/^\//,”)
    && location.hostname == this.hostname) {

    var $target = $(this.hash);

    $target = $target.length && $target || $(‘[name=' + this.hash.slice(1) +']‘);

    if ($target.length) {

    var targetOffset = $target.offset().top;

    $(‘html,body’).animate({scrollTop: targetOffset}, {duration:1600,easing:’easeInOutExpo’});

    return false;

    }

    }

    });

    });

    • I so wanted Chris’s script to work for me, but after struggling womanfully for an hour, just couldn’t do it. (Can’t say why it doesn’t work – if I knew that, I’d be able to fix it.) This little alternative, though, works a treat, and it eases. And it doesn’t need the extra id for the target instead of just the name (I gather Chris’ script needs the target element to have an id the same as the destination href but without the hash).

      Thanks.

  64. robbie says:

    I would also like to know how to get this to stop scrolling at around 100px from the top.

    Thanks, and great script.

  65. Carlo says:

    Can I do this same effect using only HTML and CSS (3)?

  66. Ross says:

    Thank you so much for posting this! Just what I was looking for. I used to avoid jQuery because there weren’t enough documented examples for me to feel comfortable implementing it (not much of a JavaScript person) but this is really good. It has a nice smooth effect (as the title states). Thanks again!

  67. Marinel says:

    Hi! It’s already working but once I put the script on my page, the lightbox won’t work. PLEASE HELP! Thanks! =)

  68. Jonathan says:

    Nice and simple, brilliant as always. Thank you!

  69. Hoyd Breton says:

    Righteous. Any idea why it doesn’t function on the mighty iPad?

  70. Alex says:

    Have a question? I’m new to jquery and I’m having and issue with Lightbox not working with this code. Are the anchor tags conflicting since both this code and lightbox rely on anchor tags to work? If so is there a way around this?

  71. if you’re getting an error $target.offset() is null …. it simply means you have a link that points to #example but the div id=”example” does not exist in the DOM.

    Replace Line 16 from:

    if (target) {

    to:

    if ($(target).length < 0) {

  72. Hassan says:

    Awesome!!! this saves me a lot of time!!
    :-)

  73. Fabio says:

    Hi to all. Is it possible to set the duration of scrolling? Actually, it seems really fast …

Speak, my friend

At this moment, you have an awesome opportunity* to be the person your mother always wanted you to be: kind, helpful, and smart. Do that, and we'll give you a big ol' gold star for the day (literally).

Posting tips:
  • You can use basic HTML
  • When posting code, please turn all
    < characters into &lt;
  • If the code is multi-line, use
    <pre><code></code></pre>
Thank you,
~ The Management ~