Published May 21, 2012
If you’ve ever used anchors on a section of your page (<a href="#id">
), you might have found yourself thinking that “brutal” access to said section is pretty ugly. …
So, I’ll briefly show you how to change that with JavaScript and jQuery.
Retrieving the first “scrollable” item from the list of items passed to the function (variable arguments):
/**
* Function to get the first scrollable element
*
* Function the get the first scrollable element among the arguments of the
* function.
*
* @author brunotm
*
* @param $ jQuery instance
* @param els dummy parameter
*/
function scrollableElement($, els) {
for (var i = 1, 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 [];
}
Function to go to a given portion of the page:
/**
* Function to smoothly scroll to an element of the page
*
* Once the animation is ended, the location hash will be replaced by the
* one that we moved to (in order to reproduce the default behavior).
*
* @author brunotm
*
* @param $ jQuery instance
* @param id Id of the element to scroll to
*/
function goToByScroll($, id, time){
$(scrollableElement($, 'html', 'body'))
.animate({scrollTop: $('#'+id).offset().top},
(time != null ? time : 800),
function () {
location.hash = '#'+id;
}
);
}
And finally, a function that will parse your page and replace the anchors (#id
) with a JavaScript function that will move the scrollbar to the desired section:
/**
* Function to add a smmoth scrolling to every anchor in the page
*
* This function will parse the page, looking for every anchor on an existing
* section of the current page and replace the default behavior (goto section)
* by a 'smooth scrolling to section' animation.
*
* It is highly advised to launch this function when the page is LOADED (i.e.
* not ready), meaning: <body onload="javascript: autoSmoothScrolling(jQuery)">
*
* @author brunotm
*
* @param $ jQuery instance
*/
function autoSmoothScrolling($) {
$.browser.chrome = /chrome/.test(navigator.userAgent.toLowerCase());
$.browser.ipad = /ipad/.test(navigator.userAgent.toLowerCase());
var locationPath = getUrlPath();
// the ipad already smoothly scrolls and does not detect the scrollable
// element if top=0; as such we disable this behaviour for the iPad
if (!$.browser.ipad) {
// for each anchor in the page
$('a[href*=#]').each(function () {
var thisPath = filterPath(this.pathname) || locationPath;
// if anchor to the same page
if (locationPath == thisPath && (location.hostname == this.hostname || !this.hostname) && this.hash.replace(/#/, '')) {
var $target = $(this.hash), target = this.hash;
// if target exists
if ($target.length > 0) {
$(this).click(function (event) {
event.preventDefault(); // prevent the 'goto target' behavior
goToByScroll($, target.substr(1));
});
}
}
});
}
}
I would like to thank Patate Aurelie DHENRY for giving me the idea of this evolution
Nowadays, you can globally enable this behavior with simple CSS:
html {
scroll-behavior: smooth;
}
See https://www.w3schools.com/howto/howto_css_smooth_scroll.asp for details.