How to scroll an HTML page to a given anchor
Solution 1
function scrollTo(hash) {
location.hash = "#" + hash;
}
No jQuery required at all!
Solution 2
Way simpler:
var element_to_scroll_to = document.getElementById('anchorName2');
// Or:
var element_to_scroll_to = document.querySelectorAll('.my-element-class')[0];
// Or:
var element_to_scroll_to = $('.my-element-class')[0];
// Basically `element_to_scroll_to` just have to be a reference
// to any DOM element present on the page
// Then:
element_to_scroll_to.scrollIntoView();
Solution 3
You can use jQuery's .animate(), .offset() and scrollTop
. Like
$(document.body).animate({
'scrollTop': $('#anchorName2').offset().top
}, 2000);
Example link: http://jsbin.com/unasi3/edit
If you don't want to animate, use .scrollTop() like:
$(document.body).scrollTop($('#anchorName2').offset().top);
Or JavaScript's native location.hash
like:
location.hash = '#' + anchorid;
Solution 4
2018-2020 Pure JavaScript:
There is a very convenient way to scroll to the element:
el.scrollIntoView({
behavior: 'smooth', // smooth scroll
block: 'start' // the upper border of the element will be aligned at the top of the visible part of the window of the scrollable area.
})
But as far as I understand, it does not have such good support as the options below.
If it is necessary that the element is in the top:
const element = document.querySelector('#element')
const topPos = element.getBoundingClientRect().top + window.pageYOffset
window.scrollTo({
top: topPos, // scroll so that the element is at the top of the view
behavior: 'smooth' // smooth scroll
})
Demonstration example on CodePen
If you want the element to be in the center:
const element = document.querySelector('#element')
const rect = element.getBoundingClientRect() // get rects(width, height, top, etc)
const viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
window.scroll({
top: rect.top + rect.height / 2 - viewHeight / 2,
behavior: 'smooth' // smooth scroll
});
Demonstration example on CodePen
Support:
They write that scroll
is the same method as scrollTo
, but support shows better in scrollTo
.
Solution 5
Great solution by jAndy, but the smooth scroll seems to be having issues working in Firefox.
Writing it this way works in Firefox as well.
(function($) {
$(document).ready(function() {
$('html, body').animate({
'scrollTop': $('#anchorName2').offset().top
}, 2000);
});
})(jQuery);
Related videos on Youtube
Comments
-
Juha Syrjälä over 2 years
I’d like to make the browser to scroll the page to a given anchor, just by using JavaScript.
I have specified a
name
orid
attribute in my HTML code:<a name="anchorName">..</a>
or
<h1 id="anchorName2">..</h1>
I’d like to get the same effect as you’d get by navigating to
http://server.com/path#anchorName
. The page should be scrolled so that the anchor is near the top of the visible part of the page. -
Juha Syrjälä almost 14 yearsI tried this and decided to use this. You were also the first and had shortest code.
-
gnarf almost 14 yearsAs far as creating a selector to find the
<h1 id="anchorName">
or an<a name="anchorName">
, use$('#'+hash+',a[name='+hash+']')
or slightly optimized$(document.getElementById(hash) || 'a[name='+hash+']')
which will search for the element by id first, and resort to searching the a's only if one isn't found. -
CodeJoust over 11 years@gnarf - There isn't any need to optimize the '#' selectors in jQuery - they're already optimized for you. It's fairly easy to see if you've read the jQuery source code.
-
gnarf over 11 years@CodeJoust - I'm on the jQuery team, I've read it many times, and yes
$("#selector")
is optimized but$("#selector,a[name='selector']")
won't go through the same optimizations as quickly. I suppose my 2.5 year old comment is a little strange sounding. The "optimization" is avoiding thea[name='selector']
search if it finds the id, not optimizing searching for the id. -
Jonathan Dumaine about 11 yearsI at first thought Mandx was trolling, then I tried this and it worked. Beyond me how I never came across this method before. Mozilla Docs for this method. Also, it appears that this will be very well supported in browsers.
-
Jazzy over 10 yearsI had some luck with this approach: <a data-hash="about">About</a> <script> $("[data-hash]").click(function() { var data = $(this).attr("data-hash"); $(document.body).animate({ 'scrollTop': $("#"+data).offset().top }, 500); }); </script>
-
Ryan about 10 yearsThat doesn't actually scroll though, it just jumps. At that point you might as well just link to the anchor
<a href="#anchorName">link</a>
-
NuclearPeon almost 10 yearsI've had a lot of issues with jquery solutions not scrolling. This saved me a lot of frustration.
-
QUB3X over 9 years@chrisツ It change the URL adding the "#anchor", right?
-
chris over 9 years@Qubex_ yes, I think so
-
Alveoli over 9 yearsneat and does it without reloading the page. Thanks!
-
Cristian Vrabie over 9 yearsNote that this will only work once. Once the hash is set, the page won't scroll to the same hash unless you change it to a dummy one then set it again.
-
nico gawenda over 9 yearsWhen you set the value, you have to omit the hash sign. "location.hash = hash;" - which also makes it pretty weird to wrap it in a function
-
Benny Schmidt almost 9 years@Ryan The question was about how to do it in javascript, not HTML.
-
jpaugh almost 9 yearsSometimes, you need to do it dynamically, though; i.e., through no direct action of the user. I believe that's what the OP wants.
-
Srneczek over 8 years-one - it doesn't scroll
-
Bill Shihara over 8 yearsThe selector is throwing an exception in jquery 2.2.0. 0x800a139e - JavaScript runtime error: Syntax error, unrecognized expression: a[href*=#]:not([href=#])
-
Markus Zeller over 8 yearsYou should not use scrollTo, because it is already used by the global window object. Also the parameter should not be named hash, because location.hash is defined, too. You may use this code:
function scrollToHash(hashName) { location.hash = "#" + hashName; }
-
AntBirch almost 8 yearsApologies for commenting on an old topic but this works best for me as my project isn't using JQuery. Only issue I noticed is that it misses off 5 pixels or so if you scroll to the very top.
-
Gherman over 7 years@MarkusZeller, why shouldn't the parameter be called hash? It doesn't collide with location, does it?
-
isherwood over 7 yearsYes, clearly the OP was already aware of anchor link functionality.
-
Markus Zeller over 7 years@German Oh, you're right. Hash is of course independent of the location object.
-
vogomatix over 7 yearsWARNING! This method can have problems if a div above it contains floating elements and cannot determine its size easily.
-
nunop over 7 yearsThis is a clean solution, however as of now it doesn't allow any tweaking, it does a hard scroll. There is an experimental parameter
scrollIntoViewOptions
that has abehavior: "smooth"
option, but it is currently compatible with Firefox only. -
Dave Everitt about 7 yearsVery refreshing to see a pure js version. I teach students to always look under the hood and understand what JQuery does for them, so this is a nice example.
-
Mark Barrasso over 6 yearsThis should be the accepted answer: it is a pure js example AND it achieves the desired scrolling animation effect. I adjusted the timeout value to 20 and it works flawlessly.
-
R01010010 over 6 yearsThank you I love pure javascript solutions
-
zai chang over 5 yearsExcellent answer that removes dependency on jQuery
-
Lying_cat almost 5 yearsHow to animate this?
-
Alexandru Trandafir Catalin almost 5 yearsWow! Works awesome!
-
stackers almost 5 yearsthis does scroll if you set "scroll-behavior: smooth;" on the html element
-
parismiguel over 4 yearsI think you should add the following to CSS style file:
css html { scroll-behavior: smooth; }
-
Smitty-Werben-Jager-Manjenson over 4 yearsNice, simple to use solution. Thanks!
-
Vincent over 4 years@SkuraZZ Best to ask a new question for this, since I just came across this coincidentally. But in any case, you can use
scroll-behavior: smooth
. See developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior -
TadLewis over 4 yearsI had to remove the multiplication by .2; it then went directly to my element. This works great if you are placing your data via document writes and you need to navigate after the page has completed loading. Straight hash navigation from the URL doesn't work in that case. Stick it in an event listener for page load.
-
Debbie Kurth about 4 yearsWorks in IOS just tested it.
-
gaborous almost 4 yearsIn the latest Chrome release this is the only method I have found that consistently works. Thanks for the tip!
-
gaborous almost 4 yearsThis solution works very very well! Thanks for sharing!
-
goat over 3 yearsNote that
scrollIntoView
suffers from the same problemscrollto(some px location)
does - if the location of the element changes as you scroll, you will scroll to the wrong position. This can easily happen if you, for example, have unknown-dimension images loading while you're scrolling, which will push the scroll target element down, and your nice fancy scroll will stop short in an over-dramatized epic fail. -
Nathan B over 3 yearssometimes this is not accurate... when the page has dynamic parts with lazy load
-
Nathan B over 3 yearsI don't see any animation here
-
Peter Mortensen almost 3 yearsAn explanation would be in order. E.g., what is the idea/gist? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).
-
Peter Mortensen almost 3 yearsWhat is "relitere"? Is there a typo?
-
Dave over 2 yearsThis CSS method works great for me and is super elegant!
-
Mikko Rantalainen over 2 yearsIf you think you want smooth scroll you should use
document.getElementById("xyz").scrollIntoView({block:"nearest", behavior:"smooth"});
so that the user doesn't get forced smooth scroll if they have disabled that in browser settings. Safari doesn't support this so it will just snap into correct position without animation. You should use this instead of scrolling to given pixel offset because this honors e.g.scroll-margin
properties automatically. Reimplementing support forscroll-margin
would be pretty complex. -
Mikko Rantalainen over 2 yearsNote that if you use web fonts with
font-display: swap
you may end up with slightly incorrect scroll offset if you measure the scroll position before the fonts are swapped in. And when you usefont-display: swap
the swapping is asyncronous and depends on client network speed, DNS servers, web font hosting CDN and client CPU power so it's practically random. The best you can do is to try to detect the event for font loading: stackoverflow.com/a/66739727/334451 -
clamum almost 2 yearsVery sexy scroll