Smooth Scrolling to Anchor with jQuery

  • follow us in feedly
Published August 20, 2013 by Brad Knutson
Smooth Scrolling with jQuery

The days of abruptly jumping to an anchor link within a page are over. Ok, maybe that is a little drastic, but honestly with all the advancements in HTML5 and CSS3, there really isn’t any reason why anyone should be abruptly thrust down a page to an anchor link.

You’ve probably seen this effect on some of your favorite sites. You click on a link, and the page smoothly and gracefully scrolls down to a specific section of content. This transition is easy on the eyes, it’s appealing, and damnit – it’s just plain cool!

I’ve worked with clients that are fascinated by this effect, and more often than not they seem to think that it would take some great engineering feet to accomplish. This isn’t the case! In fact, you can accomplish this simple effect with just a few lines of jQuery!

We’ll utilize jQuery’s built-in function scrollTop() to do our heavy lifting.

View Demo

The jQuery

Here is a simple function I wrote that will accomplish this effect.

The Explanation

The scrollToAnchor function takes in a variable, in this case ‘aid’ (or a ID, as in anchor ID). The function than generates an a tag with that variable – one that matches the anchor tag you put on your page.

Then, the jQuery function scrollTop is put to use to animate the page and gracefully scroll up or down to the new location.

In my above example, I’ve chosen to fire this function on all a tags, but you can specify which you would like by using a more specific selector. On click, we grab the href attribute, remove the # symbol, and send that variable to our scrollToAnchor function.

This example works if your HTML is set up like so:

With the jQuery that I wrote above, as long as the name matches the href, it will work automatically on all a tags!

Check out my example to see it in action!

View Demo

See? It’s not that complicated. Give it a try and let me know if you have a better solution!

Update 3-11-2014

I admit that when I wrote this post in August of 2013, I didn’t fully flesh it out and find the best solution. It does work, but needs a few minor tweaks to work in ideal situations (check out the comments in this post to see what I’m talking about).

James Pederson was kind enough to rework this function to iron out those tweaks I was talking about, and I’m happy to share it with you here (with full credit going to James of course).

Think you can top James’ solution? Let us know in the comments below!

The following two tabs change content below.
Founder at Inbounderish
Brad Knutson is a Web Developer in the Twin Cities area of Minnesota. He has experience working with WordPress and Drupal, and also has an interest in SEO and Inbound Marketing.

Keep Up-to-Date

Subscribe

Topics

See a complete list of topics discussed in blog posts here.

Check These Out

Get 2 Weeks Free! Sign Up Today! Premium Managed WordPress Hosting Genesis Framework for WordPress SEO is complex. Tools should be simple. Thesis Theme for WordPress:  Options Galore and a Helpful Support Community

66 thoughts on “Smooth Scrolling to Anchor with jQuery

  1. stephen

    I put it in my jquery/javascript files, but it isn’t working. Still jumps as usual.

    Can you please take a look at it? on the Small Business Tools page, linked in header.

    I tried several other authors codes, didn’t work either. But theirs were more complicated and required me to write long anchor links–not friendly with FAQ pages and such.

    Reply
    1. Brad Knutson Post author

      Stephen, it looks like you are using a WordPress site – in which case there will be a conflict with the $ character that jQuery uses. Try replacing all instances of the $ in your custom-scripts.js with the word ‘jQuery’ so it looks like this:

    1. Brad Knutson Post author

      It’s working now for me! I had to hit F5 on the page to refresh the script the first time I came back, but it seems to be working for me now1

  2. Gilad

    Thanks Brad for the very helpful function.
    I’ve added it to my site, and it’s working great. Only problem is when I click on the link, just before the scroll begins, the screen flickers for a second.
    You can see it when clicking on the ‘start comparing’ button on the homepage.
    Any idea what’s causing this?

    Reply
    1. Brad Knutson Post author

      Try changing the anchor tag from

      to

      And change the script to

    2. James Pederson

      This is also fixed by my comment below – the problem is that the browser still performs the normal behavior of jumping to the link unless you do an ‘event.preventDefault()’ on your click event. As such:

  3. Aaron Hoffman

    This worked for me. I’m using this on a bootstrap site with a static header so I had to add a “- 60″ after the “scrollTop: aTag.offset().top” so it wouldn’t cover up the text of the anchor itself.

    end result: “scrollTop: aTag.offset().top – 60″

    Hope this helps,
    Aaron

    Reply
  4. Dan

    This is an awesome solution! Thanks, Brad.

    One suggestion I have is to change the URL hash when the user clicks the anchor tag. This way, the user can copy and paste the URL to a friend and have the reference to the specific location on the page. Like this:

    // Change the hash
    document.location.hash = href;

    Reply
  5. James Pederson

    I made a few adjustments to accomplish the following:

    – if ‘a name=id’ doesn’t exist, it now grabs any element with the anchor ID
    – also added event.preventDefault() to fix the jumpy action in some browsers (even the newest chrome on Ubuntu jumped with preventing the default events)

    Reply
    1. Brad Knutson Post author

      Thanks James! This post could definitely use a re-write, your function is superior!

    2. Brad Knutson Post author

      James – I hope you don’t mind I reposted your function in an update at the bottom of my post. Hopefully it can help others. I gave you full credit and a followed link back to your site. Thanks for taking the time to work out the kinks!

  6. James Pederson

    Brad,

    My apologies, I made an error in my code when testing the ‘a name=”X”‘ element.

    I tested a bit more this afternoon and fixed it. This time I just made a Gist, so you can embed that and it’ll get updated if I make any further fixes, hah (otherwise feel free to copy it, and paste it in – I just didn’t want to add yet another fully commented snippet to your comment section). :) Sorry for the trouble.

    https://gist.github.com/jpederson/9496381

    – James

    Reply
    1. Brad Knutson Post author

      Thanks James! I tried the Gist (which I agree is ideal) but the font colors were hard to read. At any rate, I’ve updated the function in the post, thanks for the heads up!

  7. cbrass

    thanks alot for this post, i just stumbled on it while looking for a tuts for scrolling the webpage. this works fine for me until i made the webpage longer. it doesnt go to the exact link from top, it only stops mid-way. for example if i click on about us from the top it may stop at our services where as about us is still down. infact if i create a link from the top to the footer it will not scroll down there but just stop half way, although if i manualy scroll to where i want it to go and click the link to take it back to the top, it works fine.

    Reply
    1. James Pederson

      Just thought I’d weigh in on the plugins use on long pages. After I helped out a bit with this script, I installed it on a really long, anchor link filled site I used. So I know it works on longer pages.. http://accruejs.com

      Maybe post your code on JSBin or the like so we can see/fix it for you?

      – James

    1. Brad Knutson Post author

      Repost it to JSBin and share the link with us – you can’t paste an entire HTML page into comments sections!

  8. cbrass

    ook, i will give you the link later in the morning when i upload it, thanks for your concern, i realy appreciate it

    Reply
    1. James Pederson

      Yeah, up near the top I note it, but since the version I contributed, it will also scroll to any . Otherwise, you need to set up the normal <a / rel=”nofollow”>, and that’ll work too.

    2. James Pederson

      Let’s try that again hah. You can set up the element to scroll to in multiple ways.

    3. terry

      James, I do not know you, but if I ever win the lottery I will look you up. I almost never comment on sites, but I have to commend you. I have been looking for a script like this that actually worked. I have spent days trolling the net looking for something that my limited coding education could grasp. you are TERRIFIC! Script works great. THANK YOU SO MUCH!!~

  9. Gabriel

    The scrolling works great on a single page. Is it possible to also link to anchors on other pages (without scrolling obviously)? I’m not having any luck!

    Reply
    1. Brad Knutson Post author

      Sure – you don’t need jQuery to accomplish that. Just leave a tag like this wherever you want to link to:

      Then create your link like so:

    2. James Pederson

      This is also something I overlooked – sorry for the trouble. There’s a slight adjustment to where it checks the URL to see if it contains a hash tag – we can change it to regex to make sure the link href starts with a hashtag (this’ll correctly confirm that it’s an anchor link that’s inside the same page and not one to an external URL). Anyway, here’s the Gist:

      https://gist.github.com/jpederson/9496381

      And here’s the updated JSBin

      http://jsbin.com/giteqefi/16/edit

      Hope this helps, sorry for the trouble!

      – James

  10. Gabriel

    For some reason I’m not able to make the anchors work when clicking both from a) the page the anchor is on (works great) and b) from another page (does nothing).

    Reply
    1. Brad Knutson Post author

      It’s probably the jQuery line:

      That line is necessary to avoid a “flash” that some users experience when clicking on links. You could modify the script to only run our function on specific links, such as a link with the class of “scroll”. So if you give the scrolling links that class, you could use this as your function:

      That should allow external links to function normally, and still have the scroll animation on your internal scrolling links.

  11. f0

    I really like this, but have one small problem when using it on my site.
    I’m using the updated version 3-11-2014, which James had created, it works well, but I would love to be able to _omit_ an anchor tag from this effect, ideally using its anchor name.

    My problem is, this works against all anchor tags, which is good for my main menu to smoothly scroll to sections of the page.
    But I also have a scrolling gallery on my page, which uses an anchor tag #scroller for the prev/next buttons of the scrolling gallery.
    So obviously this anchor is also being affected here, so when the scrolling gallery is in the middle of the screen, it scrolls up a little bit.

    How could I exclude an anchor tag from this js, so I can exclude the anchor called #scroller but still have this work for all other anchor tags?

    Thank you

    Reply
    1. James Pederson

      In general, if you have other links on the page with javascript bound on them, it’s best to target the “a” tags better instead of just selecting all of them.

      As an example, instead of:

      $("a").click(function( event ) {

      Change that line to:

      $("a.scrollnav").click(function( event ) {

      With this, the page would only scroll when the clicked link that have a class of “scrollnav” – so you do have to go back through your page and add that class to the links that you want to scroll the page. This will ensure that any other links that have “#” in the href attribute will work as they normally would.

      My plan is to revisit this script and convert it into an easy to use jQuery plugin where you select the elements that’ll be affected, and then just run the plugin on them. This way, devs who use it will get more options, and it’ll be more flexible.

      Let me know if you still have other questions – I’m happy to help.

      Best,
      James

  12. f0

    Hi James, thanks for the quick reply.
    That solution works perfectly for me, I’ve just added that new class to my main top menu links and it works exactly as I want it to now. Leaving my scrolling gallery out of this class.
    Perfect. Thanks again

    Reply
  13. Lawrence

    How do we get this to work with offset? – so the scroll point is above the anchor.

    I know I can do this in CSS with padding and negative margin, but it jumps a bit on load. Thank you.

    Reply
    1. Brad Knutson Post author

      If you use James’ updated script, his line:

      calculates the point to scroll. By using something like this instead:

      could work – but I haven’t tested it.

    2. Lawrence

      Thank you Brad. Will give it a try. Another question, any reason why the code (the original)works, but once the page has sat it stops (the animation) working? Is it timing out?

    3. Brad Knutson Post author

      I’m not sure why it would stop working after letting it sit for a while, there are no timing elements in this script (other than the animation speed), and I haven’t been able to reproduce this in my production environment. Do you have a production page I can look at to troubleshoot?

    4. James Pederson

      Yeah, that’s not a behavior I’ve ever experience either. Could use a test case if you have one for us.

      Just a quick mention – I made this into a jquery plugin that can just be dropped in and used with a simple $("a").creep();. I just now added an option to control the speed, and set an offset amount – which should accommodate your needs, Lawrence. Check it out:

      https://github.com/jpederson/Creep.js

      By the way, Brad. You’re added as a collaborator on that repository, so you can add features/options/documentation/etc if you like, and it’ll be a better way to improve it and keep our versions straight.

      Best,
      James

    1. James Pederson

      Also, remember that jQuery is namespaced, so you’ll need to wrap it in an anonymous function:

    1. Ruud

      Altrough it works perfectly, I always have a special thing why things won’t work.
      So I have google maps build into my website showing custom markers to indicate stuff.
      Example of a blip jquery code:
      locations.push({name:”Sea AquariumMore Info“, latlng: new google.maps.LatLng(12.086700, -68.899556), nameT: “Sea Aquarium”});
      As you can tell, if you click on the marker, a popup opens, telling you to click more info.
      It doesnt work here, probably because #seaaquarium is not in between ” “, but in between ”, I suggest?
      Do you have a solution for this?

    2. James Pederson

      First, check to see if you’re Google Map is embedded using an iframe. If it is, there will be a decent amount of additional hacking involved in making that work, so let us know.

      If you’re using the new gmap embeds, the problem is likely that our $(“a”).click…. event is firing before the gMap is fully loaded AND the InfoWindow doesn’t have the links in it until you click a marker. You have to look for clicks inside the info window once it’s been populated with the marker content. Here’s how you attach an event listener that triggers

    3. Brad Knutson Post author

      I fixed the formatting of your code snippet :) ( pre > code on this site for future reference)

    4. James Pederson

      Oh, last note, Ruud. You’ll want to include this line after your Google Maps JS executes so that the map itself exists, hah.. I removed the ‘document.ready..’ bit because you’re attaching a new event listener after the infowindow loads, and that can’t load until the document is ready anyway.

Share Your Thoughts

Your email address will not be shown.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">