Deutsche Version medianotions.de subscribe RSS feed

15.02.2009

SmoothScroll for jQuery

Tags: JavaScript, jQuery | last edited: 02.05.2010


A short while ago I realized that jQuery, in comparison to MooTools, does not have a SmoothScroll class that allows “smooth” scrolling within a page, from one anchor to the next. I also could not find any plugins on jquery.com. Thanks to Google I found a few sites that deal with the topic and have thus created my own jQuery SmoothScroll script from different sources:

jQuery SmoothScroll

// jQuery SmoothScroll | Version 10-04-30
$('a[href*=#]').click(function() {

   // duration in ms
   var duration=1000;

   // easing values: swing | linear
   var easing='swing';

   // get / set parameters
   var newHash=this.hash;
   var target=$(this.hash).offset().top;
   var oldLocation=window.location.href.replace(window.location.hash, '');
   var newLocation=this;

   // make sure it's the same location      
   if(oldLocation+newHash==newLocation)
   {
      // animate to target and set the hash to the window.location after the animation
      $('html:not(:animated),body:not(:animated)').animate({ scrollTop: target }, duration, easing, function() {

         // add new hash to the browser location
         window.location.href=newLocation;
      });

      // cancel default click action
      return false;
   }
});

Have fun!


Bookmark or send this page

Write a comment


7 Comments

Will

19.07.2010 22:02:00

Actually, I hadn’t realized that #Name is valid for *either* of the following syntaxes:

<body id="top">
<a name="top">

e.g. var target = $(this.hash + ", a[name=’" + this.hash.slice(1) + "’]");

So, actually, the script would be improved if both were supported! :)

Bogdan visit website

11.07.2010 12:25:13

Hi Will,

thanks for you feedback! Actually the navigation is between one anchor tag to an arbitrary tag that has the matching id attribute. Like on this blog page when you click on "jump to top" the matching element is <body id="top">. Or in other words, you don’t need a second anchor tag with a name attribute.

Best,
Bogdan

Will

10.07.2010 01:51:09

BTW, changing the following line fixes the issue I mention in my previous comment.

From:
var target=$(this.hash).offset().top;

To:
var target=$("a[name=" + this.hash.substring(1) + "]").offset().top;

Will

10.07.2010 01:38:47

I think the logic is a bit incorrect if you are trying to navigate between one anchor tag to another *named* anchor tag, which is how <a href="#Blah">…</a> works by default. It tries to find something like: <a name="Blah"></a> in the DOM rather than <div id="Blah">…</div>.

It would be nice if both worked, but right now your script always assumes the latter case.

Ahrengot visit website

24.02.2010 09:56:20

Hey! Thank you for this!

I am, however, a complete javascript newbie. Could you elaborate on how to implement this, please?

Bogdan visit website

02.11.2009 17:48:54

Hey Alexei,

thanks for taking a closer look at my jQuery SmoothScroll script!

I took some time to simplify and improve the script. Point 1 should be resolved now.

As for point two: I don’t think it is the job of such a script to determine wether http://www.example.com/index.php would deliver the same page as http://www.example.com/. I think in this case the web developer needs to make sure not to mix both variants in the links of a website first of all.

Alexei

02.11.2009 15:29:24

Hey! Thanks for the snippet!
There are at least 2 cases when it fails:
1. When this.href == http://www.example.com/?id=123#foo
2. When this.href == http://www.example.com/index.php?id=123#foo and location is http://www.example.com/?id=123 (and vice-versa)
For the first one, I added && location.search == this.search to test if the query strings match.
Unfortunately, the second situation is a bit trickier, if not impossible, since the directory index can be anything.