I’d like to make the browser to scroll the page to a given anchor, just by using JavaScript.
I have specified a name
or id
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.
function scrollTo(hash) {
location.hash = "#" + hash;
}
No jQuery required at all!
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();
scrollIntoViewOptions
that has a behavior: "smooth"
option, but it is currently compatible with Firefox only.
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 for scroll-margin
would be pretty complex.
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;
<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.
$("#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 the a[name='selector']
search if it finds the id, not optimizing searching for the id.
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.
https://i.stack.imgur.com/GECAS.png
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:
https://i.stack.imgur.com/7etqH.png
They write that scroll
is the same method as scrollTo
, but support shows better in scrollTo
.
scrollIntoView
suffers from the same problem scrollto(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.
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 use font-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
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);
Here is a pure JavaScript solution without jQuery. It was tested on Chrome and Internet Explorer, but not tested on iOS.
function ScrollTo(name) {
ScrollToResolver(document.getElementById(name));
}
function ScrollToResolver(elem) {
var jump = parseInt(elem.getBoundingClientRect().top * .2);
document.body.scrollTop += jump;
document.documentElement.scrollTop += jump;
if (!elem.lastjump || elem.lastjump > Math.abs(jump)) {
elem.lastjump = Math.abs(jump);
setTimeout(function() { ScrollToResolver(elem);}, "100");
} else {
elem.lastjump = null;
}
}
Demo: https://jsfiddle.net/jd7q25hg/12/
In 2018, you don't need jQuery for something simple like this. The built in scrollIntoView()
method supports a "behavior
" property to smoothly scroll to any element on the page. You can even update the browser URL with a hash to make it bookmarkable.
From this tutorial on scrolling HTML Bookmarks, here is a native way to add smooth scrolling to all anchor links on your page automatically:
let anchorlinks = document.querySelectorAll('a[href^="#"]')
for (let item of anchorlinks) { // relitere
item.addEventListener('click', (e)=> {
let hashval = item.getAttribute('href')
let target = document.querySelector(hashval)
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
})
history.pushState(null, null, hashval)
e.preventDefault()
})
}
The easiest way to to make the browser to scroll the page to a given anchor is to add *{scroll-behavior: smooth;}
in your style.css file and in your HTML navigation use #NameOfTheSection
.
*{scroll-behavior: smooth;} Click to Scroll
other sections
other sections
other sections
other sections
other sections
other sections
other sections
other sections
other sections
other sections
other sections
other sections
other sections
it will scroll down to this section
Smoothly scroll to the proper position
Get correct y
coordinate and use window.scrollTo({top: y, behavior: 'smooth'})
const id = 'anchorName2';
const yourElement = document.getElementById(id);
const y = yourElement.getBoundingClientRect().top + window.pageYOffset;
window.scrollTo({top: y, behavior: 'smooth'});
css html { scroll-behavior: smooth; }
$(document).ready ->
$("a[href^='#']").click ->
$(document.body).animate
scrollTop: $($(this).attr("href")).offset().top, 1000
The solution from CSS-Tricks no longer works in jQuery 2.2.0. It will throw a selector error:
JavaScript runtime error: Syntax error, unrecognized expression: a[href*=#]:not([href=#])
I fixed it by changing the selector. The full snippet is this:
$(function() {
$("a[href*='#']:not([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) {
$('html,body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
}
});
});
This works:
$('.scroll').on("click", function(e) {
e.preventDefault();
var dest = $(this).attr("href");
$("html, body").animate({
'scrollTop': $(dest).offset().top
}, 2000);
});
https://jsfiddle.net/68pnkfgd/
Just add the class 'scroll' to any links you wish to animate
Most answers are unnecessarily complicated.
If you just want to jump to the target element, you don't need JavaScript:
# the link:
<a href="#target">Click here to jump.</a>
# target element:
<div id="target">Any kind of element.</div>
If you want to scroll to the target animatedly, please refer to 5hahiL's answer.
jQuery("a[href^='#']").click(function(){ jQuery('html, body').animate({ scrollTop: jQuery( jQuery(this).attr('href') ).offset().top }, 1000); return false; });
This is a working script that will scroll the page to the anchor. To set it up, just give the anchor link an id that matches the name attribute of the anchor that you want to scroll to.
<script>
jQuery(document).ready(function ($){
$('a').click(function (){
var id = $(this).attr('id');
console.log(id);
if ( id == 'cet' || id == 'protein' ) {
$('html, body').animate({ scrollTop: $('[name="' + id + '"]').offset().top}, 'slow');
}
});
});
</script>
I found an easy and simple jQuery solution on CSS-Tricks. That's the one I'm using now.
$(function() {
$('a[href*=#]:not([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) {
$('html,body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
}
});
});
A Vue.js 2 solution ... add a simple data property to simply force the update:
const app = new Vue({
...
, updated: function() {
this.$nextTick(function() {
var uri = window.location.href
var anchor = ( uri.indexOf('#') === -1 ) ? '' : uri.split('#')[1]
if ( String(anchor).length > 0 && this.updater === 'page_load' ) {
this.updater = "" // only on page-load !
location.href = "#"+String(anchor)
}
})
}
});
app.updater = "page_load"
/* Smooth scrolling in CSS - it works in HTML5 only */
html, body {
scroll-behavior: smooth;
}
Success story sharing
<a href="#anchorName">link</a>
function scrollToHash(hashName) { location.hash = "#" + hashName; }