Updated on February 18, 2017
There are several ways to scroll smoothly when clicking on jump links (anchors linking to sections within the same page) and the simple code below is from Paulund’s site.
But first the sample markup:
<a href="#services">Jump to services</a> | |
<div id="services"> | |
<p>Praesent tincidunt felis ed, a euismod quam dapibus tempus. Phasellus accumsan tellus dui. Nam ullamcorper hendrerit nunc, id eleifend dui fermentum sed. Mauris pulvinar non leo in iaculis. Nunc consequat mi lectus, sit amet egestas felis cursus sed. Proin lacinia nisl eu blandit sodales. Maecenas ultrices urna sed lectus pulvinar laoreet ut in ante. Vestibulum et maximus risus. Praesent eu sodales nunc, et accumsan lectus.</p> | |
</div> |
Step 1
Create a file named say, global.js in your child theme’s js
directory (create, if not present) having the following code:
jQuery(function( $ ){ | |
// Smooth scrolling when clicking on a hash link | |
$('a[href^="#"]').on('click',function (e) { | |
e.preventDefault(); | |
var target = this.hash; | |
var $target = $(target); | |
$('html, body').stop().animate({ | |
'scrollTop': $target.offset().top | |
}, 900, 'swing'); | |
}); | |
}); |
If you have a fixed header and would like to set an offset for the scroll position, subtract the height of your fixed element like so:
'scrollTop': $target.offset().top-120
where 120 is the height in px of the fixed header in this example.
To set an offset at viewport widths greater than a specific width, use this sample global.js instead:
jQuery(function( $ ){ | |
// Smooth scrolling when clicking on a hash link | |
$('a[href^="#"]').on('click',function (e) { | |
e.preventDefault(); | |
var target = this.hash; | |
var $target = $(target); | |
if ( $(window).width() > 1023 ) { | |
var $scrollTop = $target.offset().top-120; | |
} else { | |
var $scrollTop = $target.offset().top; | |
} | |
$('html, body').stop().animate({ | |
'scrollTop': $scrollTop | |
}, 900, 'swing'); | |
}); | |
}); |
Step 2
Add the following in child theme’s functions.php:
// Enqueue site-wide scripts | |
add_action( 'wp_enqueue_scripts', 'sk_enqueue_scripts' ); | |
function sk_enqueue_scripts() { | |
wp_enqueue_script( 'global', get_stylesheet_directory_uri() . '/js/global.js', array( 'jquery' ), '', true ); | |
} |
That’s it.
I implemented this the other day, Sridhar, but I think I need some sort of additional offset from the top as the hashed link can end up too close to the top of the screen for my liking once scrolled.
The demo site illustrates the problem if you click on About.
http://www.paulund.co.uk/playground/demo/jquery_internal_animation_scrolling/
I presume your own demo uses a separate div but I don’t want to create extra divs with padding or margins just to bring the linked element down slightly from the top.
Can you think of a way of doing this?
Thanks
When offset is needed for sites that have fixed header, I recommend Page scroll to id WP plugin.
Thanks Sridhar. That plugin’s FAQ says you can offset the scroll-to position by setting an offset value (in pixels) in the plugin. I might see how they do that and just add it manually to my code.
Cheers
Neil
Hi there,
To set an offset value of 50px for instance, just use the same code with a tiny addition:
jQuery(function( $ ){
// Smooth scrolling when clicking on a hash link
$('a[href^="#"]').on('click',function (e) {
e.preventDefault();
var target = this.hash;
var $target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top -50 // change offset value
}, 900, 'swing');
});
});
Hi Jean-Philippe,
thank you for that solution! I wonder what one could do to make that offset change conditional. Like when one has a sticky header on big screens but no sticky header on smaller screens. Maybe someone has an idea besides using the plugin mentioned by Sridhar.
Cheers,
Kimoribj
Hi Kimoribj,
I’ve updated the tutorial for sample code to account for an offset when viewport width is greater than a specific value.
Perfect, thank you!
Thank You
[…] basta con añadir un pequeño fichero con código Javascript y encolarlo vÃa functions.php. Esta página lo explica perfectamente, y si necesitas que haya un offset para que funcione igual de bien con un menú fijado en la parte […]
Thanks Sridhar…..great Work on my website….
Modern Approach (without Jquery):
var navPointer = document.querySelectorAll('a[href^="#"]');
for (i = 0; i < navPointer.length; i++) {
navPointer[i].addEventListener('click', function(e) {
var pointer = toElement.getAttribute('href').slice(1);
var elem = document.getElementById(pointer);
elem.scrollIntoView({behavior: 'smooth', block: 'center'});
var pointerH = toElement.getAttribute('href').slice(0);
history.pushState(null, null, pointerH);
e.preventDefault();
});
}
I used in my website.
[…] set up smooth scrolling to the recipe sections after clicking on the Jump to Recipe buttons follow this […]
Thank you!!
Hi,
It works very well. But this code prevents the hashlink from being added to the adressbar.
Normally it would add “#abc” anchor link at the end of the url. But it doesn’t add anymore, it just scrolls down the page.
How can I solve this?