Animated Scrolling with jQuery 1.2

read 118 comments

A few weeks ago I wrote about how to use jQuery and a couple modules from the Interface plugin suite to automatically have same-page links scroll to their target location when clicked (Animated Scrolling for Same-Page Links). Well, now that jQuery 1.2 is out, and I've successfully upgraded this site to it without a hitch, we can do the same thing with jQuery core alone.

Update

This entry is deprecated. Please see the following for more current information:

Here is what the code looks like with the minor change:

JavaScript:
  1. $(document).ready(function(){
  2.   $('a[href*=#]').click(function() {
  3.     if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'')
  4.     && location.hostname == this.hostname) {
  5.       var $target = $(this.hash);
  6.       $target = $target.length && $target
  7.       || $('[name=' + this.hash.slice(1) +']');
  8.       if ($target.length) {
  9.         var targetOffset = $target.offset().top;
  10.         $('html,body')
  11.         .animate({scrollTop: targetOffset}, 1000);
  12.        return false;
  13.       }
  14.     }
  15.   });
  16. });

Not a bad little adjustment when you consider that we're able to get rid of a plugin dependency.

One subtle change here is that we've removed the "@" symbol for the attribute selector, because jQuery 1.2 uses the CSS notation rather than the XPath. The more significant change is the way we're locating the target's position and animating the scroll to reach it:

JavaScript:
  1. var targetOffset = $target.offset().top;
  2. $('html,body').animate({scrollTop: targetOffset}, 1000);

First, we declare a targetOffset variable for the target's top offset position. This is now possible because the .offset() method from the Dimensions plugin has been moved into the core library.

Next, we animate the scrollTop property of the body and html elements to that targetOffset value, courtesy of the expanded jQuery fx module.

But why do we need to select both body and html? Well, Firefox and IE use body in quirks mode but html in standards mode. Our $('html, body') selector takes both situations into account. Of course, if you know your pages are running in standards mode (which they should), then you can drop the body (and the comma) from the selector.

Ease on down the page

Let's not stop there, though. While we're playing around with this, we can add an easing effect. All we need to do is reference the easing plugin and add our easing option to the .animate() method, like so:

.animate({scrollTop: targetOffset}, 1000, 'easeOutBack');

And if, as Dorian asked about in a comment on the previous tutorial, you want to scroll to a position 30 pixels above the target id, you can do so simply by subtracting 30 from $target.offset().top:

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

Animate scrolling within an element

Here's something really fun: with the new .animate() functionality, we can animate the scrolling of an element that has its CSS overflow property set to "auto" or "scroll."

Let's say, for example, that we have a div with an id of "scrollable" and inside it we have a bunch of paragraphs. Something like this:

Paragraph 1: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Paragraph 2: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Paragraph 3: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Paragraph 4: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Now we want to animate the scroll to the third paragraph. Before we get too far in the explanation, let's try it:

For this one, we find the difference between the div's top offset and that of the third paragraph. Then we just scroll the div to that number. Just for kicks, we'll include the "easeOutBounce" easing method as well.

Update

Based on feedback from Joel Birch and Oli in the comments below, I've changed the code below to take advantage of "relative animations," using the syntax available in jQuery 1.2.1. My initial tests showed that it's now working regardless of scroll-bar or font-size adjustments. Here is what it looks like now (not sure if storing the difference in a third variable was necessary, but it felt right to me):

JavaScript:
  1. $(document).ready(function() {
  2.   $('#scrollit').click(function() {
  3.     var divOffset = $('#scrollable').offset().top;
  4.     var pOffset = $('#scrollable p:eq(2)').offset().top;
  5.     var pScroll = pOffset - divOffset;
  6.     $('#scrollable').animate({scrollTop: '+=' + pScroll + 'px'}, 1000, 'bounceout');
  7.   });
  8. });

That's all there is to it. Have fun.

comment feed

118 comments

  1. Nice examples. The second one (two liner) is exactly what I was looking for and it works great. If anyone's interested, here's some quick code to extend it into jQuery.fn:

    
    jQuery.fn.extend({
      scrollTo : function(speed, easing) {
        return this.each(function() {
          var targetOffset = $(this).offset().top;
          $('html,body').animate({scrollTop: targetOffset}, speed, easing);
        });
      }
    });
    
    $('#my-el').scrollTo(1000);
    
  2. Excellent, Aaron! Thanks for turning that into a quick plugin. Very nice.

  3. Joel Birch

    Very interesting indeed. Something I have always wondered about getting positions in this way is what happens if the text size is increased. I tried it on this page. Notice that the "animate scrolling within an element" example still scrolls to the originally calculated position despite the text for paragraph 3 appearing lower after text scaling.

  4. Oli

    Nice example! Something little seems not to work with the top offset when you first move the scrollbar to any position and click on the "scroll to paragraph 3"-button afterwards. It does not jump to the right position and jumps forth and back.

  5. Thanks for the reports, Joel and Oli. Much appreciated. I updated the entry to fix those issues.

  6. Joel Birch

    Thanks so much for fixing that issue, Karl. I'm using Interface scrollTo all over the place, so this write-up will help me do it better and cleaner in future. Cheers muchly!

  7. enej bajgoric

    Hi For some reason this doesn't really work for me. I have jQuery 1.2 . I am also trying it on a page that is simular to this.
    http://www.cssplay.co.uk/layouts/basics2.html
    I am trying to do something like haveamint.com any help would be much appreciated.
    sorry if this is not very clear

    Thanks in advance

  8. Till

    hi,

    why the "return false"? it breaks the browser-history, and it works with "true" as well. i havent testet many browser thou.

    handy code however; i used it on my site:)

    -till

  9. @enej, I need more information to be able to help you. What exactly isn't working about it? Can you show me your page?

    @Till, yeah, that's a sticky one. Try removing the return false. You'll get a lot of back-button clicks that don't do anything except change the hash in the URL. There are ways around this sort of thing. Klaus Hartl put together a History plugin for jQuery. But that was outside the scope of this tutorial.

  10. Philip Meissner

    Doesn't seem to work in Safari 3.0. There is no animation.

    • Henri Pajala

      This didn't work in safari at first. I had to specify the image height in css to make it work. In firefox the image heights are calculated when the document.ready is called, even if the image heights are not specifien in the css. Safari doees not do it. If the image size is not specified, safari considers the images to be 0px x 0px and calculates the relative distances wrog. I got rid of this anoying bug by simply adding a height attribute to my images in css.

  11. It's very nice and it works for me but now I have installed Imagebox from Interface and your code stop to work :( If I remove interface.js it run but I really need Imagebox, I think that I need to use scroll of Interface now.

  12. Forget my last post, I find a solution. The problem with Interface site is that you can't download just file you need and when I have take Imagebox it give me a file with all Interface UI. I find on another site just files for Imagebox and now all work together. Really happy because I love your animated script. Thanks !

  13. Glad to hear you got it working!

  14. John

    Would it be possible to include some instructions on how to implement this with the history plugin? I love this effect but not being able to use the back button to return to the previous area of the page breaks usability a bit too much for me.

    I've tried to get this working with Klaus Hartl's history plugin but no joy. I'm wondering if it's due to it not being compatible with jQuery 1.2?

  15. Hi John,

    I just tested this with Klaus's history plugin, and it seemed to work fine for me. Take a look at my test page. Click on the link for the "Comment Form" to do the animated scroll. Then hit your back button.

    You'll need to add a reference to jquery.history_remote.js, add $.ajaxHistory.initialize() inside $(document).ready(), and remove the return false; from the animate-scroll script. Just "view source" on the test page, and you should see it all there.

  16. John

    Hi Karl,

    Thanks so much for the demo - but there's a problem. When I first implemented your script for the smooth scrolling, I noticed the comment from Till indicating the problem with the browser history and so I tried it with the "return false;" removed. This leaves the history intact but it makes the effect much less appealing - i.e. the page quickly jerks to the anchor and back, then it scrolls smoothly to anchor. This is what seems to happen on your test.php page too - i.e. I'm not sure the history plugin is doing anything and if it is - it's not necessary since removing the "return false;" enables the browser history anyway.

    The ideal situation would be a nice smooth scroll without the jerkiness, the history plugin adds the #anchor to the browser address bar and then a click of the back button returns the user to the original point in the page where they first clicked the anchor link.

    I wonder is this actually possible?

  17. Hi John,

    You're right about the return false bit. I should have known that. Strange that I didn't see the jerkiness when I tested. Maybe some browsers handle it better than others do. Anyway, I'll look into getting this working with the history plugin a bit more. When I tried the history plugin with jQuery 1.2.1 and the demo page that it comes with, it seemed to work fine, so I'm not sure the problem lies there. I'm getting an error when trying to build it into my script, so I might need to ask Klaus for some help.

    I should add that my instructions for using the history plugin above were woefully incomplete, showing my lack of understanding of how it worked. Sorry for the inconvenience.

  18. Just a note with how you initialise your code,
    $(document).ready(function(){
    Should be just function(){

    The reason being is that internet explorer does not reliably start your code each time if you use your method. So sometimes your scrollbars would appear in IE6, othertimes not! Not a good impression.

    Kevin luck was nice enough to point this code difference out to me while I was trying it out as well:

    http://groups.google.com/group/jquery-en/browse_thread/thread/fb17f6045c24cd9f/0a8f55a546a9d56c#0a8f55a546a9d56c

  19. John

    No worries Karl - I appreciate your efforts! I look forward to seeing if you can unearth the "holy grail" of smooth scrolling anchor links! :)

  20. bhaarat

    again, thanks a bunch!!!
    awaiting the 'load on scroll' (i think thats what it is called) with jquery. Like dzone has. loading 25 more results when user scrolling toward end of the page.

    u rule karl!

  21. very nice work. its really very helpful for anyone.

  22. Nice! just switched my website from Prototype to jQuery. (BTW, jQuery scrolling works much more smooth, you can compare with identical page powered by Prototype.)

    Your piece of code creates problems when using with jQuery LightBox and probably with many other plugins, as it scrolls to top of the page when you click on links that have '#' in their href attribute.
    (Example : 'next' or 'prev' links of the lightboxes)

    You need to change your select expression to a[href*=#]:not([href=#])

    Here is the fixed version:

    $(document).ready(function(){
    $('a[href*=#]:not([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}, 1000);
    return false;
    }
    }
    });
    });

  23. @Brett, in the thread you refer to, Kelvin suggests replaceing window.onload with $(function() {. The $(document).ready(function() { line in my script does the same exact thing as Kelvin's $(function() {. The only difference is that $(function() { is shorthand.

    @Anton. Sorry about that problem you experienced with lightbox. You're right that there is a conflict there in my script. Actually, I've already implemented a slightly more robust solution, and I plan to write an update entry on it soon. Cheers.

  24. ben

    sorry the html didn't come up properly:

    <div id="nav">
    <a href="#one">one</a>
    <a href="#two">two</a>
    </div>

    <div id="one">
    </div>
    <div id="two">
    </div>

  25. Hi Ben,

    It looks fine to me. Are you including the jquery.js file in the <head>? I might need to see a sample page that is exhibiting the problem in order to help troubleshoot.

  26. ben

    Yeh i'm adding the jquery.js file.....and i had other jquery things working on the same page. here's a link to the page - http://www.vocle.com/jquery/hor.html

    its probably something really obvious...so sorry in advance. thanks for the help Karl!

  27. Hey Ben,

    I think I see the problem: You're not using jQuery 1.2+. You're using version 1.1.4. :)

  28. ben

    hahah that exactly the problem! i downloaded the script a while ago and am only learning it now.....i've upgraded it and got it going perfectly. thanks so much for your time - and thanks for the tutorials - they're great for learning how to use the scripts!

    is it possible to have the same scrolling effect go sideways? i'm thinking about making a site with just one really wide page and have it scroll sideways to each part, is that possible?

  29. josh

    hi, please give me some installation instructions. what do i need to do to get this working.

  30. how do i get the bounce option to work when using this code

    1.
    $(document).ready(function(){
    2.
    $('a[href*=#]').click(function() {
    3.
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'')
    4.
    && location.hostname == this.hostname) {
    5.
    var $target = $(this.hash);
    6.
    $target = $target.length && $target
    7.
    || $('[name=' + this.hash.slice(1) +']');
    8.
    if ($target.length) {
    9.
    var targetOffset = $target.offset().top;
    10.
    $('html,body')
    11.
    .animate({scrollTop: targetOffset}, 1000);
    12.
    return false;
    13.
    }
    14.
    }
    15.
    });
    16.
    });

  31. @Marlon

    Get jQuery.easing and add, as third parameter of jQuery.fn.animate (line 11) the one you like. For example:

    $('html,body').animate({scrollTop: targetOffset}, 1000, "easeOutBounce" );

    By the way, this article is great!

  32. Ariel,

    Thanks a lot for answering the question. And I'm glad you like the entry. Be sure to check out the improved version, too.

  33. Jim

    I'm curious how I could integrate the scolling with your show/hide accordion tutorials?

    I've got a long list of accordian items - and when I open/close one - the page sticks at the bottom - but it would be nice to scroll back to the object that the user clicked on to open the div (h3).

  34. Very nice scrolling , high so ;)

  35. FYI I'm getting a javascript error caused by examples.js when the page loads, in both FF2 & IE7.

    FF: $target.offset() has no properties
    IE: 'offset().top' is null or not an object

  36. Hi Wick,

    Thanks a lot for the heads up on the JavaScript error. Turns out it was being caused by some mangled HTML in a comment someone posted. All should be good now. Thanks again.

  37. Tom

    Thank you,

    i was searching for exactly this one :-)

    I never thought that JQuery is so easy to work with, but thanks to your blog, i managed it.

  38. This is exactly what I was looking for. Thank you so much for putting this out there. I did, however, make a small improvement that adds the hash to the URL and allows you to use your back button. Simply add location.hash = this.hash; just before the return false; like this:

    $(document).ready(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}, 1000, 'easeOutQuad');
            location.hash = this.hash;
            return false;
          }
        }
      });
    });
  39. Hmm, on further inspection, this causes a little bit of jumping around... You can add a timer delay to the hash change to eliminate the jumping, but then the back button unfortunately doesn't work. Oh well.

  40. Hi Joe,

    thanks for sharing your attempt to get the back button working with this. I actually implemented something similar a while ago (but using the improved script as my starting point). The trick is to add the hash to window.location in the callback of the .animate() method. Here are the relevant lines:

      		  $('html, body').animate({scrollTop: targetOffset}, 400, function() {
      			  if (!location.hash) window.location += target;
      		  });
    

    Hope that helps!

  41. Karl, adding it into the callback does provide the ability to click "back", but the window doesn't actually scroll back to where you were before the animation started. I used Joe's method, because while the screen does "jump" initially for about half a nano second (I can BARELY even notice it, and my computer is by no means awesome), the ability to hit back and scroll back to where you were is very useful.

    i also trimmed down the code quite a bit, but that's because I know all of my #hash links are internal. Also, that's part of the fun of jQuery, seeing how short you can make the code. :) Anyways here's what I ended up with, working good for me.

    
      $('a[href^=#]:not([href=#])').click( function() {
        var x = $(this.hash);
        if( x.length ) {
          $('html,body').animate( { scrollTop: x.offset().top }, 500 );
          location.hash = this.hash;
          return false;
         }
      });
    
  42. Matt

    Hi, is there a way to only have these behaviors occur in a certain div, and have everything outside of that div behave normally when you click on an anchor?

  43. Hi Matt,

    Yes, you can certainly limit the onclick handler to a certain subset of anchors. It's all in the selector.

    For example, you could change $('a[href*=#]') to $('#mydiv a[href*=#]') to limit it to anchors inside the div that has an id of "mydiv."

    That said, you might want to take a look at the improvements I made to this script, or better yet, Ariel Flesler's ScrollTo plugin, which he says was inspired by my improved script.

  44. ABDC

    Thank you VERY much for that tutorial. My site uses very long pages and a lot of inpage links so this helps to keep your orientation while navigating.

    How could I make the page scroll as well when coming from another page via a deep link? I think I would need to select the location, look for a # then execute the above code, but I have no idea how to manipulate the location like that!? Any help appreciated thanks!

  45. Schmappel

    Hi Carl,

    Great tutorial, thanks a bunch! I have a little question though. At the moment it only works when clicking a # link. Would it be possible to make it work upon loading a remote page, say for example example.htm#linkname?

    Thanks again!

  46. Schmappel

    Hi Carl,

    Great tutorial, thanks a bunch! I have a little question though. At the moment it only works when clicking a # link. Would it be possible to make it work upon loading a remote page, say for example example.htm#linkname?

    Thanks again!

    Ps. Just now I notice ABDC seems to ask the same thing...

  47. Eduardo

    I am really new to jQuery and I am having a hard time figuring out how to implement this, exactily what files do I need and what code triggers the scrolling. Also the example doesn't work, I hit the button and it doesn't scroll.

  48. scb

    The example for "Animate example within an element" doesn't work.
    Clicking on the button does not scroll the div. It doesn't produce any js error also.
    (I'm using Iceweasel/2.0.0.10 )
    Thanks for the script :)

  49. Thanks for the heads up, scb! Apparently, I had deleted the <script> reference at some point. It's back now, and it's working.

  50. good for you carl. been wondering why this is not working on my safari its a windows version

  51. gran trabajo!, muy bueno

  52. Bon article sur les différentes possiblité de jquery, merci

  53. Great, works perfectly. Infact I was trying with the old one (using the interface library) and apart from the fact that was giving an error with the dequeue function it was dependant on that library that I didn't needed apart for this scoll functionality.
    Thank you

  54. Ryan

    Hi there. I'm new to jquery (and I'll warn you, I'm no programmer!), but I've gotten other jquery plugins to work properly recently. Could you indulge this probably-simple-to-understand-question-for-programmers? I'm trying to put a link in my footer and an anchor at the top of my #content div and provide smooth scrolling -- without constraining the size of my #content div.

    Put more simply, I don't want to smooth-scroll within a div, I want to smooth-scroll the whole page from bottom to top. (I know I've seen it done before, I just can't remember where.)

    Thanks!

  55. Tal Einat

    Thanks for this, it is clear and to the point and it helped me get my div auto-scrolled in minutes!

  56. Mike

    Man, this works 10/10 in FF, but absolutely doesn't work in Opera 9.5 and IE 7 (in my case, of course). In Opera, after clicking the link (which points to #div), the page is brought to top and then some ugly animation is performed on my #div (looks like very fuzzy slideDown effect). In IE, no animation is performed, works just as a standard html anchor.
    Please, any help/suggestions?

  57. Hi Mike, Thanks a lot for reporting these problems that the script is having with Opera and IE. I've updated the "improved" script. Please check it out and let me know if it fixes your issues.

  58. Mike

    Karl, the link you provided doesn't work :(.
    P.S. I'm using your code to scroll the whole page to top, like Ryan described in post #60.

  59. Hi Mike, Sorry about the problem with the link. It's fixed now. I understand what you're going for, and the improved script is meant for whole-page scrolling.

  60. Shir Gans

    Hi,

    I'm quite noobie in this field. Can someone write in plain english "what to put where?" .
    I have downloaded jQuery just now, and i am interested in applying this cool scroll.

    what do i need to add at the head script, at the seperate file script, and in the body html?

    Thanks

    • I tried to post instruction here, to no avail, I posted it on my site, (with link back here webmaster..) so you can see the simple version. I know I usually need that version.
      seointexas DOT com SLASH autoscroller DOT html
      THANKS!

  61. Awesome!, thanks for the tip for scrolling within an element.

    Blessings!

  62. CHris

    hi i love this tut but how would i get back to the top of my block instead of goin down more? thanks Chris

  63. jen

    Hi Karl, This is Jen, the person who asked about the Serial Scroll at the FOWD workshop. I'm implementing it now, and realizing that it appears that this works only for same-page links. I'd like to use it to scroll from page to page, since it is the bio component that is changing. Other than rebuilding my page to include all content in one page, is there a way to accomplish this? Site in reference, inkpixelspaper.com/clients/louriecutler

  64. First of all, thanks for the post. It's helped me solve an ongoing issue of scrolling to a particular position in a scrollable div without shifting the whole page.

    Ok, now that's said, I found that if you click on the "Scroll to paragraph 3" button and then click it again while it's still animating it will mess up the offset calculation and actually scroll to an undesired position. Is there a way to disable the click event of the button until the animation is complete? Or is there an alternative solution?

    Thanks

  65. Hey Sam,

    That's an excellent question! jQuery has a selector for elements that are animated (:animated), so you could use that. Here is a revised version, with some optimization included as well:

    $(document).ready(function() {
      $('#scrollit').click(function() {
        var $scrollable = $('#scrollable');
        if (!$scrollable.is(':animated')) {
        	var divOffset = $scrollable.offset().top,
            pOffset = $scrollable.find('p:eq(2)').offset().top,
            pScroll = pOffset - divOffset;
        	$scrollable.animate({scrollTop: '+=' + pScroll + 'px'}, 1000, 'bounceout');      
        }
      });
    });
  66. Sanjay

    This is a very helpful post and I could implement this for scrolling 'to' an anchor. However, what if I need to scroll back to the original place. Is there a generic method I can use without specifying the location to go back to? An equivalent of history.back in jQuery?

  67. Raj

    Thank you!

    This article really helped. I'm totally new to javascript not that good at it but managed to get the site working like I wanted thanks to this article!

  68. inv

    Thanks for the article, got one problem with the script though.
    Please, can anyone check this test web site: http://inv.blink.pl/test/ - the second link is using the same method, but got no idea why it doesn't work properly...

    And the second issue - how to decrease bouncing rate in this example? The only parameter i can change is timing...

    thanks :)
    inv

  69. can i use this in google blogger??

  70. that is not work by me? why?
    I use Firefox 3 now

    • I have no idea why it isn't working for you. You haven't given me any information about the problem you're having. Did you see the update at the top of the post? There are newer, more robust solutions available. Please visit the pages I linked to. Thanks.

  71. rb

    any chance on updating this function to work with jquery 1.3?

    • It works fine with jQuery 1.3. Please see the update mentioned in the entry above. Also, you can test the script yourself by clicking on the "xx comments" link at the top of each entry. If you're having a problem getting the updated script to work with a particular browser, please let me know.

  72. I find that I need "html,body" for Google Chrome, even in standards mode.

  73. Great article Karl, nicely written. I'm new to web design and have a pretty basic knowledge, but do you know any other way to do that scrollable area (without the bounce) in css?

    • Hi Rory, I'm not sure what you mean by "do that scrollable area in css." Would you mind clarifying? To create a scrollable area, you need to set a height or width and set the overflow property to either auto or scroll.

  74. Hi, the script works fantastically smooth. However, I also need to link certain anchors to another page. This seems to be prevented by this script and the anchor in question gets just tagged to the end of the current url, eventhough the target url is hardcoded in the link itself.

    I would really appreciate your help to see if this script can be extended to that as well.

    Regards,

    Marius Ooms

    • Hi Marius,
      I'm not sure I understand the problem you're having. Are you saying that the script won't let you visit another page if the link has a hash? That shouldn't be happening, as the script only binds to links that match the pathname and hostname of the current document. Also, you might want to take a look at the improved script.

      • Karl...thanks for replying! First off, other related question, I use WordPress and you must use the jQuery call instead of the Dollar sign. e.g. I have to write jQuery(document).ready(function() instead of $(document).ready(function(), but must I also do this for $target?

        As far as the linking goes...links without a hash work fine, but I'd like to visit an anchor on another page from the current page. Say I am on the following url:


        http://mysite.com/story1/

        This page has a link to the front page with the following anchor:


        <a href="http://mysite.com#twitter">Go to twitter</a>

        Now I assume it should just go to the new url and anchor. However, the current url just changes to the following:


        http://mysite.com/story1/#twitter

        My other option is to turn of this little script on all other pages other than the front page, but than I could use scroll anchors anywhere else.

        I appreciate the help. I not super good with jquery other than simple animation ;)

        Regards,

        Marius

        • Hi Marius,

          First, about the "$" symbol. You only need to replace that when it's the function name. When a variable starts with "$" you can keep using it. Also, if you want to use "$" in your script, you can write your ready function like this:

          jQuery(document).ready(function($) {
            // Use $() without colliding with other libs;
          });
          

          As for your problem, I haven't been able to reproduce it. See this test page.

  75. Thank you for explaining Karl also for setting up the test page. At least now I know where else to look. Possible wordpress is at fault.

    Lastly...is it possible to use somewhere:


    return false;

    In order for the anchor names not to show in the url bar?

    That's it, I promise ;)

    Regards,

    Marius

  76. Cam Marshall

    This is a total stab in the dark here seeing as how this thread is so old... I am a total noob at jQuery coding, and I'd like to add this effect to my site.

    Is there anywhere where I can do a step-by-step tutorial on how to implement this into my existing code?

    Any help would be greatly appreciated! Cheers...

  77. Great article! Clear and concise. Thanks!

  78. realog32

    Very helpful.
    U r d man, mate.

  79. Hi. Thank you for this script, it was very useful for me.
    I want to offer you one quick and dirty but helpful fix:

    var frame = ($.browser.safari) ? $('body') : $('html');
    frame.animate(…);

    The main idea is that only Webkit needs to scroll BODY element, all other browsers (FF, Opera, IE) needs only HTML. But scrolling both elements cause Opera to scroll page without animation.

  80. can some one tell me how to write it into a function to auto scroll when page loads?

  81. Great post! Thanks for this. Really helpful.

    cheers!

  82. very helpful hint the $('html,body') selector for scrolling the page

    thanks!

  83. victor

    Just curios. I am extremely new to web design and coding. Is there a way to achieve an animated scroll using only HTML?

    Might be a crazy question but it's worth a try.

  84. thx for the information...

    firstly, i made code like this..
    $("#images li").animate({left: "-=ImageWidth"}, "slow")

    but it wont work...
    after i saw your code above, i modified the code to..
    $("#images li").animate({left: "-=" + ImageWidth + "px"}, "slow")

    now it works.... hehehe...
    thank you very much...

  85. Ben

    Hi Karl,

    This blog is exactly what I was looking for very useful although I am new to jquery, infact this my first time using it and wondered if you could help me. Basically I have pasted the code be between in between the head tag as I'm not sure how elso to save it and relate it, I have the locations I want it to scroll to set as

    go to top

    and the link set as

    although it doesn't seem to be working, excuse me if I am making a simple mistake, I am atempting this action with know knoledge of jquery as of yet but hoping to learn it quickly.

    One other thing, once I have got it working, is it possible to change the speed of the scroll?

    Any help would be much appreciated.

    Thanks Karl

    Ben

    • Hi Ben,

      Can you provide a link for me so that I can see what's up? If not, then make sure you at least have a reference to the jQuery core file before your custom script.

  86. Max

    Hi Karl, I'm new to jquery but while messing around with it I noticed two things.

    Number one, the animation is executed twice when doing $('html,body').animate(); This is hard to spot with a naked eye but if you print a message in a complete: callback to a firebug console you'll see it. This happens in firefox, haven't tested other browsers.

    Number two, if you have a super small paragraph at the bottom, so that the top of the scroller can't get to it, you notice that the animation would still be running even though the scroll slider has reached the bottom. Again visually it's hard to notice but if you wanna run a second animation you'll notice a small delay between them. Or when you try to move a slider you'll see it jumping since the animation would try to move it down. I guess this will never happen if animation is move the slider up since the scrollTop will always reach the top of a target regarless how small the target is.

    Max.

    • Hi Max,

      Please take a look at the improved version of this script and see if that solves the issues for you.

      • Max

        I ran your improved version. The first issue, which is animation being called twice, is gone. But the second is still there. The only way to see it is to make the animation really slow, say 5000ms and put a console.log('finished'); inside the callback. Then put a div at the very bottom say 1000px.

        When you run the animation you'll see that the scrollbar stops at the bottom but the animation still runs ie. there is no print-out in a console. After sometime the print-out will eventually appear.

        I think what happens is the scrollbar reaches the end but the scrollTop still has to reach the target top. So it looks like it's finished but in fact the .animation is still crunching numbers.

        So the solution I came up with is to calculate if the scrollTop can ever reach the target top, if not I calculate the lowest location the scrollTop can reach and then scroll to it. This way when the scrollbar reaches the bottom of the container the animation stops.

        Here's a code snippet,

        var contentHeight = contentWrapper.outerHeight(true);
        var scrollableHeight = scrollable.outerHeight();
        var targetTop = target.offset().top;
        var offset = targetTop;

        if ((contentHeight - targetTop) < scrollableHeight) {
        // scrollbar will reach the bottom before the scrollTop will reach the target top

        offset = contentHeight - scrollableHeight;
        }

        The content wrapper is needed because you need to know the height of the content. You also have to keep in mind that the the height of the content might be wrong if the margin is collapsed. To fix margin from collapsing you'd have to set the overflow property of the content to hidden.

  87. James Albuquerque

    how can i make this scroll horizontal?

  88. Great job with this script. Thank you for writing something simple and easy to implement! This is exactly what I needed for a project I'm working on.

  89. david

    I have a question about part of the code for this example. I follow the logic of the script but don't understand the syntax with this portion:

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

    I know it's short hand for an if else statement

    my questions is assigning the value $target.length && $target to the target variable. So if $target.length && $target then target equals <$target.length && $target . I guess I'm just not sure the role of the double ampersand in assigning a value to a variable.

    Thanks for your help,
    David

  90. Too complex compared to how Scriptaculous deal with this feature ....

    • It's only complex because it attempts to handle some edge cases. If you know how you're writing your hrefs and you're sure that the elements you're linking to exist, then you can simplify it quite a bit. Also, this is an outdated version of the script, as noted in the entry.

  91. th3mon

    Thanks for all guys!
    But... If you must have some space above element I add some attribute to function:

    
    jQuery.fn.extend({
        scrollTo : function(speed, easing, val) {
            return this.each(function() {
                var targetOffset = $(this).offset().top + val;
                $('html,body').animate({
                    scrollTop: targetOffset
                }, speed, easing);
            });
        }
    });
    
    And you put somethig like this:
    
    $('#element').click(function(){
            $('#target').scrollTo('slow','swing',-20);
        });
    
  92. Metin METE

    hi karl... i've tried so hard but i could not . IDs in transition to different pages, how to add animation?

    thanks

  93. rod

    This is awesome, Just downloaded the lates version of the plugin and it works like a charm. I'm already testing it everywhere in once of my webpages. thanks!

  94. Thank you for your nice tutorial, although I was looking for to scroll horizontally. I have got something : http://plugins.jquery.com/project/SmoothDivScroll and http://www.smoothdivscroll.com/, hope this will help some people. Thanks!

  95. Karl,

    Great post; I've actually just started getting into jQuery. I was gonna ask if there were any books that you'd recommend for a beginner like myself? Something like jQuery for dumbies?

    • Thanks, Ben.

      There are a number of good books out there. jQuery in Action 2nd edition is solid. My co-author and I are finishing up the 3rd edition of Learning jQuery, which is great for beginners. The new edition will have some more advanced chapters as well.

  96. Having a little trouble with this and hoping I can get some help. It seems to be partially working.
    Here is the link
    http://fourcemag.kenaesthetic.com/homme/index.htm
    look at the designers and brands box. I modified the code to follow an A instead of a P but I still get the page scroll but a little animation... ?
    Thanks

  97. Thedrake

    Hi

    The first code doesn't work. It bugs at this line:

    $('[name=' + this.hash.slice(1) +']')

    Afte checking on jQuery's site, you need to surround the value of name with " "

    $('[name="' + this.hash.slice(1) +'"]')

    this line works.
    Anyway, that's what I was looking for... thank you very much!

27 Pings

  1. [...] Learning jQuery » Animated Scrolling with jQuery 1.2 (tags: jquery javascript howto webdesign web development design library animation animated scrolling) [...]

  2. [...] I've posted a new entry about how to achieve the same effect (and more) using jQuery 1.2, without the need for any of the Interface plugin modules: Animated Scrolling with jQuery 1.2 [...]

  3. [...] hatte ich ja mal bei Learning jQuery etwas dazu gelesen, dort werden alle Sprünge zu Ankern mit einer Animation [...]

  4. [...] código (scroll.js) lo encontré en el siguiente artículo: http://www.learningjquery.com/2007/09/animated-scrolling-with-jquery-12 Advertencias: Este código es compatible con ie7,ie6 y firefox. Existen problemas de compatibilidad [...]

  5. [...] scrolling, using its animate function and the “scrollTop” parameter. Karl Swedberg covers this technique on his great website Learning [...]

  6. [...] do animated scrolling, using its animate function and the “scrollTop” parameter. Karl Swedberg covers this technique on his great website Learning [...]

  7. [...] scrolling, using its animate function and the “scrollTop” parameter. Karl Swedberg covers this technique on his great website Learning [...]

  8. [...] scrolling, using its animate function and the “scrollTop” parameter. Karl Swedberg covers this technique on his great website Learning [...]

  9. [...] scrolling, using its animate function and the “scrollTop” parameter. Karl Swedberg covers this technique on his great website Learning [...]

  10. [...] scrolling, using its animate function and the “scrollTop” parameter. Karl Swedberg covers this technique on his great website Learning [...]

  11. [...] scrolling, using its animate function and the “scrollTop” parameter. Karl Swedberg covers this technique on his great website Learning [...]

  12. [...] is straight-forward, and is easy to add to any page. The javascript code is taken from this page: Animated Scrolling With jQuery. I found that tutorial a little hard to follow ( I think it is written for people with far more [...]

  13. [...] Animated Scrolling with jQuery 1.2 [...]

  14. [...] Animated Scrolling with jQuery 1.2 [...]

  15. [...] 该方法的原作者是:learningjquery.com 里面介绍有更多jQuery实现的效果,如果你英文好的话可以移步学习一下。 [...]

  16. [...] completo de página: Ver Contenido‘ JQUERY SCROLL TO Ver Contenido‘ SMOOTH SCROLL Ver Contenido‘ ANIMATED [...]

  17. [...] Animated Scrolling with jQuery 1.2 [...]

  18. [...] This scroller seems to work without the “jump” we were experiencing. [...]

  19. [...] do animated scrolling, using its animate function and the “scrollTop” parameter. Karl Swedberg covers this technique on his great website Learning [...]

Sorry, but comments for this entry are now closed.