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 :)
This is a little easier to understand but they both do the same thing
Chris’ snippet doesn’t work smoothly with my website in Chrome . But, for some reason, Devin’s works like a charm.
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.
Yes, this is a good point – i couldn’t get it to work myself, and didn’t figure out at a first glance, but this is important:
There also need to exist the elements with the corresponding ID’s with those of the hashes .
E.G:
Those using the method :
<a href=”#test”>go to hash</a>
and in your code:
<a name=”test”>try to get here</a>
This doesn’t work with the code above,
I myself have changed the line:
var $target = $(this.hash), target = this.hash;
to:
var target = this.hash;
var $target = $j(this.hash).length>0?$j(this.hash):($j(‘a[name='+target.replace(/#/,'')+']‘));
This way it works with both the ID and the A name=… versions
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.
on the line:
increase/decrease the number from 400 to whatever you want, to achieve the desired speed. For instance, I increased this number up to 1600 in order to achieve the effect I was looking for.
Thanks for this great code Chris!
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
Thanks for posting that link, I was having a weird problem where on click, the page would start to scroll then half way through it would jump to the anchor. Your edits fixed it up.
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?
I am having this exact same problem.. does anyone have a solution?! I’m using anchors with a fixed header, and when I click on the links to the anchors, it scrolls them up behind the fixed header. I’ve tried a few different things, but alas, no success..
I will be so thankful for any help!!
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.
Hello!
I had a problem with the code above wherein upwards smooth scrolling does not work. I tried your code and it works in Chrome, IE9, FF and Opera! Thank you very much for sharing.
@Chris McClean – Thank you so much for this script! I’ve been trying to find a “linked anchor” script that scrolls the page, but also doesn’t interfere with href’s that have the hash (#) symbol stand-alone within them (as those types of href’s typically are used with other JS functions). You’re brilliant! :)
@ Chris McClean – I’ve got one issue with your JS… When a page’s URL has a trailing slash (e.g. example.com/page/), the page doesn’t scroll. Works fine if the page’s URL ends with ‘.php’ or ‘.html’, etc. Any thoughts on how to get your script to work with the trailing slash in a URL?
$(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; }); });Oh my lord! thank you so damn much for including comments in your script, I am so new to js that there are plenty of times that I just can’t figure out what is doing what. Yours is the first script that was so clearly layed out that I was able to understand what was happening in it. I am forever in your debt… and I want to be best friends! Thank you so much Chris Mclean!
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:
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!
scrollTop: (($(target).offset().top) – 41)
where 41 is the topbar height.
thankyou
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)?
Have the same question here…
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 ;)
thank you, awesome!
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.
Me too! I have a fixed header above the scrolling page and want the scrolling to stop where the section is still below the fixed header, not behind it! :(
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.
Big thanks for the script!
The script was failling first because I was using <a name=”foo”> instead of elements with id’s, and secondly it would fail when the target element wasn’t found.
Changed this:
To this:
And it works out of the box with existing mark-up.
I was having problems getting this to work on my site and couldn’t figure out why. But I implemented your change and it works now. Thanks!
Hej.
If you guys are using jQuery tabs or any other jquery or anyother script as a matter of fact that also uses the # tag to do something I have a quick fix for that, edit this line:
$('a[href*=#]').each(function() {to
$('a[href*=#wrap]').each(function() {You change the default a[href*=#] by changing the # it targets.
In my case I do my sliding with the hash tag #wrap …
So I modified the code so that the scrolling targeted only my wrap thus a[href*=#wrap]
I hope you folks understand, honestly I don’t at this moment. But it does work. Now my jquery tabs work perfectly along with the smooth scrolling.
cheers
i tried this, then my scrollTo doesnt work, if there is a way to exclude a set class or id that would work best. you are including from the sounds of it one set of anchors.
Sweet script, I’m using it on a redo of my portfolio site I hope to put up in the next week. The site is also using twitters bootstrap and I ran into a problem. If I want to use the bootstrap tabs, this code scrolls the page up to the top.
Bootstraps tabs use anchors and anchor links. So I was wondering if there was any way to set your code to only notice ancor links within a set ID. I’m not a coder so please excuse my ignorance. – Jeff
Doh, Jalokims example works for me too, don’t know how I missed his comment.
So I changed all my anchors that I want the smooth scrolling on to start with #nav and set that up where Jalokim used #wrap in the JS code. Then I can use #navhome #navgallery and so on for the smooth scrolling anchors and any anchors that don’t start with #nav won’t smooth scroll!
Hey, Great Tutorial. I was wondering how one would offset the scrolling of the div from the top of the browser window to be offset say 150px from the top of the browser – I have a fixed positioned header occupying this space and would like the div scrolling to the top to come just below this.
Any help would be great!
I’d love to know an answer to this as well (I have a fixed header)
. I’ve tried editing the $target.offset like so:
but that doesn’t seem to have much of an effect on things, alas.
Insert -40 (or whatever height your header has), but after ScrollTop:targetOffset, not after $target.offset().top – so the code should read:
$(scrollElem).animate({scrollTop: targetOffset-40}, 400, function()…
I was having the same problem too, and was trying to figure out why the “jerking” behavior happens with the fixed header . This is why—the animated process works in this order:
First, it animates the screen position to the anchor location by number calculation. Then, it puts the hashtag into the location. So, the code is actually moving the screen twice! You just don’t see it on the second move because it’s already been moved into position!
However, if you’ve got a fixed header and try to account for it in the offset, you will then see the jerk backwards because it is calling the hashtag position on the second move.
I have two ways I currently deal with the fixed header issue:
1. If I must preserve the hashtag, then Stefan in the comments here has a good CSS offset solution.
2. If I don’t have to preserve the hashtag, then I just remove the call for the hashtag anchor, like this:
$(scrollElem).animate({scrollTop: targetOffset-60}, 1000);Hey Chris, fantastic work. I was playing around with the example and was able to minify it as well as tackle some of the “issues” addressed in the comments.
This code below (based on your work) allows for both same site links with hashes (ie, referencing another article on another page), as well as external.
For troubleshooting, the $(‘body’) (vs) $(‘html’) would be the first change if this is not working, all else should be good.
It is also really easy to add the hashes back to the browser address bar, however, it seems better UX wise to leave them off. – that is just my viewpoint though.
(jQuery 1.7)
This solved my problem regarding the offset, and it’s smaller. Thanks Eric! Fingers crossed that their aren’t any issues : )
Alas, using “body” for
seems to break things for Chrome : ( anybody have any tips?
I’m working with anything slider v1.5.17. For some reason it’s not playing in Internet Explorer 7. It works fine in 8 and 9 but for 7it only shows the first image and the controls disappear. Am I missing something?
IE7 is old, don’t develop for it
Thnx alot! it works perfect! but except mobile devices.. Is there a way to make this script works on mobile devices too?
Thnx!
Hey Chris!
Fantastic Article one question though,
How can I reference this in another file, probably a simple thing but I’m sorta a newbie :)
– Allen Lawson
See Demo on my site = ajwebdesigner.in
This works perfectly, just paste the code with jQuery and ready to go :D
Thanks Chris. !
I’m using the base url meta tag on all my pages and /#top/ would simple redirect me to the homepage.html#top … is there any solution for avoiding that to happen?
hey there,… im kinda new to code. I have this thing working great in safari but not firefox. any tips?
Thanks
Looking for a scrollTo designer for a Business Directory webpage:
(see) http://www.vtlsuccess.com/Directory.html
I want (1) an accordion effect to display a Business Directory of Product-Service Categories (4 columns of roughly 25 categories each in the white-center-middle column below the navigation row on the page above. The column-list shown is 1100px L X 227px W).
Every product-service category name will eventually have an active link that can display details of the exclusive business supplier for that category.
Visitors to the page will be looking for a provider/supplier of a particular product or service. They first search the alphabetical directory and click the category they’re looking for. (2) The detail information about the provider should be displayed either as a pop-up window in front of the page or in a cell in the right-blue column on the page. I like Ariel Flesler’s “jquery.scrollto” effect for this latter action (see demos.flesler.com/jquery/scrollTo/ and/or http://flesler.blogspot.com/2007/10/jqueryscrollto.html. The displayed information should be printable.
Once the code and installation instructions for the above capabilities have been provided, I will need to know how to set-up i.e. activate the links and input and/or change information about the suppliers as there will be continual additions and changes.
I have Dreamweaver CS3 and Photoshop CS5.
John Hogue
John@VTLSuccess.com
Questions:
Can Accordion Widget work Side-to-side as well as up and down?
Can Accordion panels contain Links, Lists,Tables?
Can Srollto. Event occur in separate column from Trigger?
I have this working great, with the exception of the “Back To Top” link. It just jumps up with no smooth scroll. Any ideas would be greatly appreciated.
http://kspersonaltraining.ca/index.v2.html
Cheers
This is the correct easing code:
// Animate to target
$(scrollElem).animate({scrollTop: targetOffset}, 1100, ‘easeOutElastic’, function() {
I added ‘easeOutElastic’ for a bouncing effect!
Do not forget to add the jQuery easing pack.
This worked for me. But used it with ‘easeInOutExpo’
Hi there, I noticed that when I implemented the code that the scroll animation would scroll to the wrong spot and then jump (like a normal href=”#*”) to where it was supposed to go when the window was resized. The issue seems to be that the offset gets determined basically on page load which screws up fluid/percentage based layouts since they reflow and change the actual offset. The solution I end up with was to just calculate the offset on click instead.
To do so replace this:
with this:
Thanks for this Derek.
I’m experimenting using DropBox to build a html5 site and had the same problem.
Replacing this piece of code fixed it.
By the way: this works on a Mac with every browser I can throw at it. Also worked on my Explorer 6 test station. I’m not using php or any other scripts.
Wonderful work Chris.
Thanks Derek. The initial script is great, but if you are building a responsive design, the anchors are slightly off upon changing size. This script fixed it.
Thank you for the example. I realized when I reference a target that does not exist, it fails. Basically your logic to “Ensure target exists” needs a little adjustment.
I replaced the following
with
Now it works every time.
Thank you!
i have this working well, except i have some tabbed content as well and since this looks for any anchor # i want to write in an exception. I know enough JS to be able to read it, but not enough to write in my own exception.
It is easier than this if you are only interested in the content area of your website. For instance, I have no interest to jump to links in the sidebar, so I changed the source like this:
var scrollElem = scrollableElement('.span9');//'html', 'body'
In my example, I am only interested in the div with class span9.
Thank you, thank you, thank you!
Yes, very well done — thanks @Tony and @Derek for the tweaks!
Hi All,
Not sure if this question has been answered before but how would I modify the script so that it scrolls from a javascript call command to an anchor rather than the a[href*=#]. Some of my pages don’t have straight links but rather javascript calls to an anchor.
This is a great tutorial but there have been so many comments that it gets hard to follow after a while. Thanks in advance.
@Haldun is right — doesn’t work with mobiles, at least iOS…
Chris McClean’s Solution seems to work on both iOs and standard browsers.
Hi i’m trying to insert this fantastic effect in my web site at this page :
http://www.martinimarmi.it/marmo.html
my ideas is to set the links in the center-left div and when clicked scroll the center-right div to the anchor. But the metter is that i’m not so good with javascript ( yes! and with english too, sorry), so i ask help to you.
Please if you have any ideas help me.
I use chrome and opened the Java console and copy pasted the script.
the error was TypeError: Cannot call method ‘ready’ of null
Hi All, I am trying to impliment this on my page but cannot get it to work yet. It appears in the head tag when I use firebug (it’s a drupal site and as such I put it into the reference to the file into the .info theme file) however I cannot get it to actually work. I have also flushed the cache. It’s at http://icanw.org.uk/cms/ -if anyone has any ideas I’d be thrilled to hear them – thanks!
I have a fixed header and its returning #NaN with the following code (but functioning) :
$('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 - 220; $(this).click(function(event) { event.preventDefault(); $(scrollElem).animate({scrollTop: targetOffset}, 600, function() { location.hash = target - 220; });Any thoughts on how I could get the desired effect without the NaN?
I’m having the weird #NaN issue, too. I hope there is a fix for this. What a bummer, the offset trick is working beautifully otherwise!!
I’m using Derek and Tony’s modified code, if that helps troubleshooting any…
Hello everybody!
Like this script very much well done! It work fine on my static page, but now im trying to us the script on a wordpress installation. And won’t get this to work. This kind of the “$” and jQuery concflict, but not exactly i think… I tried to replace all the “$” in the script with “jQuery” and it didn’t work either… I ididn’t expect it to though. Lines like ” $scrollElement = $(el); ” are also causing conflicts… So my question where exactly do i have to change the “$”? Or is there another solution fpr my problem? I tried no conflict but didn’t work…
BTW I had that fixed header problem as well. My solution was to give the anchor a class “goto” and then style it with display:block; a padding with height of my header and a negative margin with that same height. Like:
a.goto { display: block; margin: -69px 0 0; padding: 69px 0 0; }
The padding would then push my content beyond the fixed header at the top of the viewport, and the negative margin “negates” the block display, so that everything is still in place. Hope that helps…
The fix via padding works. Thanks for that!
Works like a charm. Thanks you much. Worked immediately for me :)
Can this be used for commercial purposes i.e. for a corporate website?
Thanks
Hi, this is jasmine. Today i met with a problem. My table is being moved up when i use the firebug in my webpage. Currently am working in eclipse. Can anybody help me to sort this out?
Thanks to Derek!
Hi there. Excellent snippet!!
Just one change to make: when the link grabbed points to something (an object) that doesn’t exist in the DOM, it crashes.
The solution is to check if the object you point-to really exists. To make this happen, just change the ‘if’:
if (target) {to
Solved.
Great snippet!
And I found solution for header “bug”. Variable target is a string so you cannot contract from it. So instead changing hash in callback function, simply do if after animation.
Ok, there was problem with scrolling after hash change in previous solution for header “bug”. Here my new fix:
It works, but can sombody explain my why traget id change back to original after callback function? I thought I will have to do it manually.
This works! Just add the desired value after “top” then add:
$(target).attr(‘id’, ‘tmp’);
after the animate line!
THANK YOU!
Hi there.. I am using this scrolling in my container(centered on page). I have a pinned(fixed) menu on the left of the screen. AIf I take the window to a smaller size, and I pick a menu item it scrolls down and then left over my menu. I it posible that this is because of the scrolling? IF yes, how can I disable it?
Thanks.
Love this effect but have noticed a bit of a usability problem with it. I implemented it in to a client website and then noticed that if you want to navigate using the BACK button it starts going though all the anchors that you have used which is quite annoying.
Would be awesome if there was a solution to this whereby people could still leave the page with one click on the ‘back’ button after using them.
Anyone got any ideas?
Hi Tom,
Only thing You have to do is to remove fallback function for animation. So instead:
you write:
Anyway, I think that registering anchors is more userfriendly, couse it’s imitate page by page navigation, if You know what I mean.
Hope that help.
Thanks a lot of that! I think it depends on how its implemented. I can see instances where cycling back would work and instances where it wouldn’t.
Either way its good to know that this can be done if needed :)
Thanks Chris, works perfect.
This script is very close to working for me but I have two variables not resolved. Could someone provide a concise script with these options built-in? I’m sure it would help a lot of other people that I’ve read on many other sites looking these same requirements.
1.) I need to target links by class to avoid the script breaking other features on the pages.
2.) My anchors on this wiki do not use an id, but rather – name=”my link”
If anyone is interested have a look too at this new template – Slidexy – we’ve put together: http://www.tallhat.com/templates/slidexy/ – it uses jQuery and also is responsive as it also presents the same content well on iPhone and iPad.
I found that this script called jQuery.LocalScroll works within the parameters I outlined above. It does not appear to handle headers that have more than common alphabetical letters, so commas, question marks, etc will make it revert to default anchor link teeth-jarring movement.
I like the script on this page very much, but for this big wiki I’m working with I just could not get it to function without targeting link classes or parent container and using name=link” on anchors rather than id=link”. I will return to use this script on other projects someday and will happily make a donation too -
If anyone has a fix to let this work on an iPad as well, please let us know!
Perfect, this is just what i’ve been looking for.
Is it possible to combine this with other jQuery plugins to speed up load time? (without breaking the code)
How do we get this to work on an iPad? Thanks!
Your code fails in a couple of browsers (IE, Chrome and Safari … FF seems okay) if they’re zoomed out. It appears to be because of how you check to see if the container is scrollable. The following lines seem to be the issue:
$scrollElement.scrollTop(1); var isScrollable = $scrollElement.scrollTop()> 0;I’m guessing when the browser is zoomed out, scrolling by one doesn’t scroll at all (which, funny enough, makes 1 NOT more than 0). Changing to 2 will probably fix the issue well enough.
I just read this webpage: http://djpate.com/2009/10/07/animated-scroll-to-anchorid-function-with-jquery/
and found I can do this with the following code:
function goToByScroll(id){$('html,body').animate({scrollTop: $("#"+id).offset().top},'slow');
}
it’s a little bit smaller than yours, I’m wondering what yours does which this doesn’t
Excellent Post, Works Great… I have applied to my blog..
Check it out here at “YourBloggingTips – Smooth Anchor Linking”
I have applied both the methods, one provided in the post & other from “Reference Url – Page Source”
Both seems to work properly.
The changes I have made to
scrolling speed,target.offset& small changes to// Ensure Target ExistsFollowing is my complete modified code which works 100%
AWESOME ! thanks a lot it helps me for a project !
Hi all, for some reason I can’t get this to work on this site and page in particular: http://milemarker.com/?page_id=1060
Any help would be much appreciated.
Thanks!
Awesome, thank you!
One question though:
I’m designing a website that has a fixed position top bar, so when you scroll down the page it stays at the top of the screen. This means that when I direct to a certain part of the page, say a line of text, it is hidden by the top bar. Is there anyway to offset the scrolling destination a number of pixels so the part of the page I want the user to see is not hidden by the top bar?
I hope that all makes sense.
Thanks in advance!
Hey chris do you know how to get the hash mark from appearing at the end of the url. I doont want nothing to be added to the url if its a has bookmark link. If you know the code please tell me where in the above code would i place it
Oh my, thank you so much ! I was wondering if anyone would have the good lines of this function, but yours works ! It’s such a relief !
Thanks so much. Implemented on the page I am currently working on and it looks fantastic!
One quick question though, if I may.
How can I have the target ID name (hash) NOT to be displayed in the URL? Is there a way?
I made something like this a while ago:
Hey there, thanks for sharing. This is genius!
This works with responsive site, in real time too. The solution posted doesn’t work upon browser resize for responsive design (w media queries) but yours worked! Thanks again!
Ah btw I am trying to achieve something to “push” the target location by, say 120px, like this:
The current layout i’m using is blocking my h1, it’ll be nice if it can “pull/push” the end target location with the code above.
The original example Chris provided does not work with Safari 6.0.3 for OS 10.8.3, but this one you’ve posted above totally kicks butt and even has the hashtag bizness. Way cool! Thanks for posting this!
Hi thanks this is great stuff.
When i view my site on an ipad sometimes the scrolling works and sometimes it does not. Have others experienced this?
Any suggestions to get around it?
The site i am building is
http://www.risrani.com/newsite/risrani.html
You could also change:
To:
So that the anchor tag’s attribute “href” starts with rather than just contains a hash.
Hi there,
I have the same issue on the ipad as you mentioned. It worked with major delays on my end. Not sure what caused it but i’m looking for alternative too.
Hi, the code seems to work fine if your click an anchor and then you go all up of the page and click another, but if you want to navigate anchor by anchor without going to the top it’s a disaster
How do I do to make it work like in this website: http://happycog.com/ ?
Also wondering how to get it to work like happycog.com – but compatible with iphone/ipad. Any help or direction would be great! Thx.
Having issues. I am new to jquery and I am using the code as it was displayed in the tutorial. Come to find out the client is pulling my page in with an iframe. Is there alterations to be made to the code to make it work or is it borked from the get go? Ifthere alterations anyone have any ideas to what those might be? Thanks in advance. I sincerely appreciate it.
$(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);
return false;
}
}
});
});
I’m using the plugin from the refence link and I can’t get it to work: I’m have a Scroll/Follow Sidebar (from here http://css-tricks.com/scrollfollow-sidebar ) whose links I want to have the smooth scrolling applied. It works returning up, but it won’t work going down (the links don’t work at all..)
Here is the file http://cl.ly/3h3i3p0h0m34191F0T2h
Can someone help me figure this out? Thanks in advance
Plugin is not working in the newest Safari 6.0 (Mountain Lion)
if i want to add scrolling efect like “easeOutExpo”
where should i put it, and if i can ?
btw grate jquery, realy usfull :)
loved it!
Chorny
Amazing. Thank you so much.
For some reason…This no longer works in Safari 6.0 after the Mountain Lion Upgrade.
I can confirm this. Hopefully will have time to update someday.
Thanks for confirming this. Perhaps somebody with a workaround or solution might jump in and save the day.
I don’t have Mountain Lion so I can’t even try.
Yepp. Mountain Lion spoils it! Cant nail the reason…
Ok, seems not to be a code problem, rather a buggy Safari:
https://discussions.apple.com/thread/4145775?start=0&tstart=0
It seems related to the jQuery .scrollTop() function.
For some reason, Safari 6 scrolls the element correctly with,
but reports an incorrect value right after with,
But most interestingly, Safari 6 will report the CORRECT value if you call the function one more time,
I brushed up a quick and dirty test page to demonstrate this behaviour at http://www.cybmed.com/w/safari6bug.
Thanks for solving this and wow that’s some detailed explanation and solution you have there.
Hope this got fix (by Safari) sooner than later.
Just posting to keep updated.
I love this smooth scrolling, it works for me fine without any problem. Thanks a lot for such good scrolling.
Anyone able to get this working on Safari 6.0 ? Or at least a way to have normal anchor (jump t0) functionality work?
This seems to have stopped working in some versions of Chrome. Any advice?
bug in Safari. 50% solution – url changes do not work
jquery upgrade to 1.8
arrange for the smooth scrool ios
Here’s a good explanation by Johnny to the bug mentionned above:
This comment was posted on Safari 6 breaks my JavaScript.
Hi, well done for your script I need to works from an external link is there any solution, when page loads get that effect.
This is really great, and I managed to get it working perfectly it seems even though I don’t understand a single thing of javascript. However, I’ve just also used this navigation technique that uses an anchor and so creates a delay when the reveal nav button is pressed as the hidden menu thinks it is meant to be scrolling.
This is a wild stab in the dark, but do you know a simple method of excluding a particular anchor tag?
Hi,
This is a great Snippet, but recently i found an issue with Safari.
Safari doesn’t recognizes the anchor tags named with “id”, just with “name” attribute.
But the script doesn’t work with this method, so in Safari the anchor’s didn’t work.
Someone found any solution?
Thanks everybody.
Just signed up for updates. Going to play with this technique when I get home.
I’ve got a similar question to Sascha’s above. This script works fine for all the hard-coded anchors on my page, but I also have a “Find” button using this script:
function jumpToAnchor() {
window.location.href = String(window.location).replace(/#.*$/, “”) + ‘#’ + document.getElementById(‘findname’).value;
}
and this markup:
select name=’findname’ id=’findname’ class=’selectOne’
input type=”button” value=”Find” onClick=”jumpToAnchor()”
and this doesn’t do the smooth scrolling but jumps directly to the link. Is there a way to incorporate smooth scrolling into this logic?
Thanks for any help.
This looks like a pretty bigger crunch of code to actually target and have a smooth scroll on the page…, this is what i would have done to make the smooth scroll….
$(document).ready(function() {
$(document).scrollTop($(“div.wrapperBlock”).offset().top); /This would be wrapper of the page/
$(“ul.nav li a”).click(function(){ /Here you can edit your HTML CSS Structure/
var endPoint = $(this).attr(“href”).replace(“#”,”");
var target = $(“a[name='"+endPoint+"']“);
if (target.length)
{
var top = target.offset().top;
$(‘html,body’).animate({scrollTop: top}, 1000);
return false;
}
return false;
});
And the HTML would be
About
Definitely would you have done has a meaning behind it, however i would prefer this simple code.
WAY too much code for this functionality.
Here, check this post out, only 4 lines of jQuery do the same magic: jQuery: Smooth Scrolling Internal Anchor Links – By Charlie Evans.
Works perfect. Doesn’t conflict with Bootstrap Carousel.
appreciate for your work and really nice resource on your site ………
why cant you provide a plain page with only the necessary code.. without external links; link to homepage, ads and stuff.. so confusing!
I’m having trouble implementing this code. It’s interfering with Bootstrap’s Carousel. I wrote a longer post on this in the forums, but I thought I would ask my question here too. When I click on the arrows in my carousel, the page jumps down to the top of the carousel. Also, the URL changes to “mydomain.com/myproject/#mycarousel.” How can I stop the page from jumping and the URL from changing? Thanks for your help.
As I mentioned just above your post, try this code instead: jQuery: Smooth Scrolling Internal Anchor Links.
Pulkit Goyal replied to my post saying that the script above doesn’t conflict with Bootstrap Carousel. You might want to contact him vis his website if needed.
Also, you may want to use
(e).preventDefault();on your function to stop the anchor links from activating.Locally, this was working perfectly. However, now that my website is online, occasionally the smooth scrolling doesn’t work. When I click the links, it just does nothing. Then when I refresh, it’s fine… any ideas as to why?
Fixed link…
kswedberg’s github smooth scroll
Cross broswer, great options.
Here’s a fix to get it working in Safari :)
Hola muchas gracias, funciona 100%. Mi pregunta es y si quiero que se desplace horizontalmente como se puede lograr esto? Gracias
Juan, el plugin que menciona Nick debajo, kswedberg’s github smooth scroll, parece tener la opción de hacer scroll horizontal de acuerdo a lo que leo en la documentación:
direction: 'top', // one of 'top' or 'left'No sé si sea eso lo que estés preguntando.
PD. De arepa yo sé Español, pero te recomiendo que siempre postees en Inglés, así sea machacado, no importa. Es la manera más eficiente de recibir ayuda.
Hi, do you know if this works in IFRAMES?
Can I use this code snippet for commercial purposes as well?
Thanks in advance for an answer.
Best regards
Chris’s code works well, however the shorter code by Devin Sturgeon and Weremoose etc… has a noticable performance lag on all other links when initialising the Firfox(PC) window.
In addition to the post above I have now discovered Chris’s code does indeed have some lag (but noticeably less). If we target the selector a little more then this completely eradicates the delays on other links. $(‘#header a[href*=#]‘).each(function() { …
I am a complete novice to web design. Trying to implement the smooth scroll on my site. I have created the anchor links, now just need to include the smooth scroll. Can anyone please provide a step by step on how I can do this please?
Thanks for this.
Works on my project well!
Thanks a lot! But this doesn’t on Safari (v6.0.2). Can someone help me to solve this?
AWESOME!!!!!!!
i was searching for this from about last one hour….thank you dude…….
Your site is best in CSS and jQuery tutorials……i’am fan of you……thanks……… :)
hi, im not so good with jquery but im pretty good wid css and html i just want a simple thing: a link and when i click it, the page scrolls smooth to a tag h1 with id=”here.” can u please send me a code which i just have to copy and paste and can u add comments as to where i have to write the id or make any changes… pls pls pls i really want this. Please send the code with comments to my email: bornforeducation@gmail.com
How can i scroll it horizontal? =(
This fixes the Safari issue for Mountain Lion but you have to specify an ID or Class for the trigger.
Cheers
Can you please mail me the total demo file please!!
If anyone is still having trouble with iPad’s and the navigation becoming un clickable after the first click. I have found a hack to get around this problem. You will have to add a div just before the closing tag of the last element or container you are scrolling, then use jquery to set the height to 1px before the animation runs then using a callback on .animate() set the height back to 0px after the animation is finished.
Code I am using here:
And am placing a div with the id of device just before the end of the content I am scrolling.
Credit where credit is due I found this solution here:
http://stackoverflow.com/questions/7826868/fixed-position-navbar-only-clickable-once-in-mobile-safari-on-ios5/10030251#10030251
after about an hour of searching. I hope this may help someone.
Holy friggin’ comments! Thanks for this! Totally what the doctor ordered tonight.
sorry guys, I’m totally new to jquery.
I embeded the jquery google library link in the head tags.
I put the provided code between head tag or even after body tag, nuthin worked.
I simply want when I click on < a href=”index.html#point1″>
The browser moves slowly to < a name=”point1″>
Thanks in advance.
What if I want an external?
Example: Location index page have a link
Gallery 06
Redirects to the gallery page and scroll to id=”06″
How to keep the anchor link?