I\'ve been trying to add a smooth scrolling function to my site for a while now but can\'t seem to get it to work.
Here is my HTML code relating to my navigation:<
If you have a fixed navbar, you'll need something like this.
Taking from the best of the above answers and comments...
$(".bs-js-navbar-scrollspy li a[href^='#']").on('click', function(event) {
var target = this.hash;
event.preventDefault();
var navOffset = $('#navbar').height();
return $('html, body').animate({
scrollTop: $(this.hash).offset().top - navOffset
}, 300, function() {
return window.history.pushState(null, null, target);
});
});
First, in order to prevent the "undefined" error, store the hash to a variable, target
, before calling preventDefault()
, and later reference that stored value instead, as mentioned by pupadupa.
Next. You cannot use window.location.hash = target
because it sets the url and the location simultaneously rather than separately. You will end up having the location at the beginning of the element whose id matches the href... but covered by your fixed top navbar.
In order to get around this, you set your scrollTop value to the vertical scroll location value of the target minus the height of your fixed navbar. Directly targeting that value maintains smooth scrolling, instead of adding an adjustment afterwards, and getting unprofessional-looking jitters.
You will notice the url doesn't change. To set this, use return window.history.pushState(null, null, target);
instead, to manually add the url to the history stack.
Done!
Other notes:
1) using the .on
method is the latest (as of Jan 2015) jquery method that is better than .bind
or .live
, or even .click
for reasons I'll leave to you to find out.
2) the navOffset value can be within the function or outside, but you will probably want it outside, as you may very well reference that vertical space for other functions / DOM manipulations. But I left it inside to make it neatly into one function.
$("#YOUR-BUTTON").on('click', function(e) {
e.preventDefault();
$('html, body').animate({
scrollTop: $("#YOUR-TARGET").offset().top
}, 300);
});
If you download the jquery easing plugin (check it out),then you just have to add this to your main.js file:
$('a.smooth-scroll').on('click', function(event) {
var $anchor = $(this);
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top + 20
}, 1500, 'easeInOutExpo');
event.preventDefault();
});
and also dont forget to add the smooth-scroll class to your a tags like this:
<li><a href="#about" class="smooth-scroll">About Us</a></li>
Do you really need that plugin? You can just animate the scrollTop
property:
$("#nav ul li a[href^='#']").on('click', function(e) {
// prevent default anchor click behavior
e.preventDefault();
// store hash
var hash = this.hash;
// animate
$('html, body').animate({
scrollTop: $(hash).offset().top
}, 300, function(){
// when done, add hash to url
// (default click behaviour)
window.location.hash = hash;
});
});
fiddle
with this code, the id will not appear on the link
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth'
});
});
});
// styles.css
html {
scroll-behavior: smooth
}
Source: https://www.w3schools.com/howto/howto_css_smooth_scroll.asp#section2