Code Snippet
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 [];
}
});
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
:)
There is a Reference URL above with a working example.
D’oh! Didnt see that lol
Will have a go when I get home as I think I’ve spotted where I went wrong.
Thanks :)
I LOVE U!!!! i been tryna find how to do this for months! :-)
works like a charm.. thanks so much.
Thank you so much for this script. Took me awhile, but I got it to work!
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? :)
Made a new reference URL.
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?
You can try to use the jQuery noConflict technique. Read about it here: http://api.jquery.com/jQuery.noConflict/
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.
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
Does this work with Left & Right too?
Just change “top” to “left” ?
Sweet! Thank you
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?
Is the #nav positioned absolute [relative to body] or fixed? That might be the reason.
Work perfectly
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!
Technique #1 let’s you keep the hash links, while Technique #2 does not.
Both examples work great.
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
website
Thanks for this Chris! I was trying to do this with Jquery.LocalScroll, this is so much easier!! Saved me a huge headache, thanks.
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?
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.
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.
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
Awesome, works brilliantly. Barely having to do anything. Thanks Chris
Superb, worked like a charm.
Thanks!
Hello..
Just wondering if you had checked this in Opera… getting some funny results when running some tests… v.nice never the less.
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.
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
works like a charm! thanks a bunch!
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.
Thanks for the post, i’ve been trying to get something like this working for ages. Any ideas how to alter the scrolling speed?
Did you work out how to alter the scrolling speed? I’d like to do this too.
i used to grab the local scroll for this function. yours works as good. thank you.
Demo Here
http://jsfiddle.net/KRmJG/
Got this one to work straight away after hassle with the jQuery LocalScroll
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…
Ok… thankfully that didn’t take too much to figure out.
Using the second method I used this code and it worked:
Thanks for this!
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?
I have external anchor links on my page that doesn’t work anymore when using the script :-(
Chris Coyer for President!
If you want to prevent that the animations “queue up” replace this line:
$('html,body').animate({with this:
$('html,body').stop().animate({Yay!!!
Thank you sooooo much, my website is 10x better looking now and your code was so easy to use!
xo
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?
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
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. :)
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
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.
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…
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.
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
Hi,
I would also love to know how to add easing?
Thanks Chris
hey thanx this code helped us a lot
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!
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;
}
});
});
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!
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;
});
});
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.
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.
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:
Do you have any idea for me?
Thank you in advance!!
Keep on with your great work,
Sascha from Germany
Great blog post. Code “just works”!
Thanks for posting..
- Sri
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.
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!
I was getting this error too. Its was happening because i didnt have the anchor id in place. i.e.
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!
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() {
I tried this and it stops the animation completely. Here is a jsfiddle of the issue. http://jsfiddle.net/VEpgV/
Great script by the way – thanks for sharing!
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
targetinif (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.
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!
Thanks! Did exactly what I wanted and wasn’t bloated with pointless features.
Any plans to post this on Github? :D (pretty puleeeeez!)
Great script! But its not working on ipad/iphone. Does anyone know any fixes to this?
Thanks!
Love this script, but I also have the issue above. Not working on ipad/iphone. Any fix for this please?
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.
Works ty!
I would also like to know how to get this to stop scrolling at around 100px from the top.
Thanks, and great script.
yeah i’m having the same issue, did you ever figure this out?
Can I do this same effect using only HTML and CSS (3)?
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!
Hi! It’s already working but once I put the script on my page, the lightbox won’t work. PLEASE HELP! Thanks! =)
Nice and simple, brilliant as always. Thank you!
Righteous. Any idea why it doesn’t function on the mighty iPad?
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?
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) {Actually it’s > not <
I guess I got my gt and lt mixed up ;)
Awesome!!! this saves me a lot of time!!
:-)
Hi to all. Is it possible to set the duration of scrolling? Actually, it seems really fast …
anyone know how I set an offset? I want it to stop scrolling say, 50px above each target.
great thingy !
stumbled across it and went to build a page around it immediately :)
going sideways doe. everything works tipytopy.
am wondering if its possible for it to scroll in different angles?
If i lets say get to the 4th page to the left and scroll down half a page per
example and then want to go to the page on the right (that actually starts half a page
higher than i am now) of it it goes directly
right. id love it to go 45 degrees up/right (northeast).
making sense ? im working around it but its messy.
would love to know if its doable? tnx a bunch.
all the best, c
ps: not necessary 45° , 38° is even better
Hi,
I would love to use this awesome script, but somehow it doesn’t work on my page.. Any idea why?
http://www.sderidder.nl
cheers!
I got it to work now, but when i run the w3c validation tool it gives some errors.. http://validator.w3.org/check?uri=www.sderidder.nl&charset=%28detect+automatically%29&doctype=Inline&group=0
any idea? thanks
ohw, and it doesn’t work for me in Safari..
Thanks!, not work for me because I have jquery 1.6 and this is for 1.4.
But is good information. I will try with other solution. Thanks.
DigWP
A book and blog co-authored by Jeff Starr and myself about the World's most popular publishing platform.
Quotes on Design
Design, like Art, can be an elusive word to define and an awfully fun thing to have opinions about.
HTML-Ipsum
One-click copy to clipboard access to Lorem Ipsum text that comes wrapped in a variety of HTML.
Bookshelf
Hey Chris, what books do you recommend? These, young fertile mind, these.