Skip to content

Instantly share code, notes, and snippets.

@eyecatchup
Last active September 8, 2023 06:32
Show Gist options
  • Save eyecatchup/d210786daa23fd57db59634dd231f341 to your computer and use it in GitHub Desktop.
Save eyecatchup/d210786daa23fd57db59634dd231f341 to your computer and use it in GitHub Desktop.
Smooth Scroll behavior polyfill

The Scroll Behavior specification has been introduced as an extension of the Window interface to allow for the developer to opt in to native smooth scrolling. To date this has only been implemented in Chrome, Firefox and Opera.

There's a complete polyfill here (3.3KB minified). But most of the times, the following is enough for me (641 bytes minified):

smooth-scrolling-poyfill.js

Use as: scrollToElem('#elem-selector');

// native smooth scrolling for Chrome, Firefox & Opera
// @see: https://caniuse.com/#feat=css-scroll-behavior
const nativeSmoothScrollTo = elem => {
window.scroll({
behavior: 'smooth',
left: 0,
top: elem.getBoundingClientRect().top + window.pageYOffset
});
};
// polyfilled smooth scrolling for IE, Edge & Safari
const smoothScrollTo = (to, duration) => {
const element = document.scrollingElement || document.documentElement,
start = element.scrollTop,
change = to - start,
startDate = +new Date();
// t = current time
// b = start value
// c = change in value
// d = duration
const easeInOutQuad = (t, b, c, d) => {
t /= d/2;
if (t < 1) return c/2*t*t + b;
t--;
return -c/2 * (t*(t-2) - 1) + b;
};
const animateScroll = _ => {
const currentDate = +new Date();
const currentTime = currentDate - startDate;
element.scrollTop = parseInt(easeInOutQuad(currentTime, start, change, duration));
if(currentTime < duration) {
requestAnimationFrame(animateScroll);
}
else {
element.scrollTop = to;
}
};
animateScroll();
};
// detect support for the behavior property in ScrollOptions
const supportsNativeSmoothScroll = 'scrollBehavior' in document.documentElement.style;
// smooth scrolling stub
const scrollToElem = elemSelector => {
if (!elemSelector) {
return;
}
const elem = document.querySelector(elemSelector);
if (elem) {
if (supportsNativeSmoothScroll) {
nativeSmoothScrollTo(elem);
} else {
smoothScrollTo(elem.offsetTop, 600);
}
}
};
var nativeSmoothScrollTo=function(a){window.scroll({behavior:"smooth",left:0,top:a.getBoundingClientRect().top+window.pageYOffset})},smoothScrollTo=function(a,f){var c=document.scrollingElement||document.documentElement,d=c.scrollTop,g=a-d,k=+new Date,h=function(e){e=+new Date-k;var l=parseInt;var b=e/(f/2);1>b?b=g/2*b*b+d:(b--,b=-g/2*(b*(b-2)-1)+d);c.scrollTop=l(b);e<f?requestAnimationFrame(h):c.scrollTop=a};h()},supportsNativeSmoothScroll="scrollBehavior"in document.documentElement.style,
scrollToElem=function(a){a&&(a=document.querySelector(a))&&(supportsNativeSmoothScroll?nativeSmoothScrollTo(a):smoothScrollTo(a.offsetTop,600))};
@technik300
Copy link

arrow function expression in IE11:
const nativeSmoothScrollTo = elem => {
... and other
replaced by:
const nativeSmoothScrollTo = function(elem) {
and it works.
TNX!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment