animated-scroll-to

Lightweight (1.45kb gzipped) scroll to function with a powerful API. Scrolls window or any other DOM element.
The main difference to other libraries is that it accepts speed of scrolling instead of duration. This way scrolling for 200 pixels will last less than scrolling 10000 pixels. Minimum and maximum duration are configurable and set to reasonable defaults (250 and 3000ms).
All changes are tracked in CHANGELOG.
Demo
Play with the live demo.
Features
- Accepts speed per 1000px instead of duration
- Scrolls window or any other DOM element horizontally and vertically
- Returns a promise with a boolean flag which tells you if desired scroll position was reached (for IE you'll need to include a
Promise
polyfill) - If called multiple times on the same element, it will cancel prior animations
- Optionally prevent user from scrolling until scrolling animation is finished
Usage
Grab it from npm
npm install animated-scroll-to
and import it in your app
import animateScrollTo from 'animated-scroll-to';
animateScrollTo(500).then((hasScrolledToPosition) => {
if (hasScrolledToPosition) {
} else {
}
});
Method signatures
Library has three ways to call it:
function animateScrollTo(y, options);
function animateScrollTo(coords, options);
function animateScrollTo(scrollToElement, options);
Example usage of each method:
animateScrollTo(1000);
animateScrollTo([1000, null]);
animateScrollTo([1000, 500]);
animateScrollTo(document.querySelector('.my-element'));
Options
Options with their default values:
const defaultOptions = {
cancelOnUserAction: true,
easing: (t) => --t * t * t + 1,
elementToScroll: window,
horizontalOffset: 0,
maxDuration: 3000,
minDuration: 250,
speed: 500,
verticalOffset: 0,
};
Easing
By default library is using easeOutCubic
easing function. You can pass a custom function only considering the t
value for the range [0, 1] => [0, 1]
.
To make things easier I provided a list of common easing function below:
const EasingFunctions = {
linear: (t) => {
return t;
},
easeInQuad: (t) => {
return t * t;
},
easeOutQuad: (t) => {
return t * (2 - t);
},
easeInOutQuad: (t) => {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
},
easeInCubic: (t) => {
return t * t * t;
},
easeOutCubic: (t) => {
return --t * t * t + 1;
},
easeInOutCubic: (t) => {
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
},
easeInQuart: (t) => {
return t * t * t * t;
},
easeOutQuart: (t) => {
return 1 - --t * t * t * t;
},
easeInOutQuart: (t) => {
return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
},
easeInQuint: (t) => {
return t * t * t * t * t;
},
easeOutQuint: (t) => {
return 1 + --t * t * t * t * t;
},
easeInOutQuint: (t) => {
return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
},
};
Certain CSS properties might break the animation
As library is using an animation loop to scroll, some CSS properties might clash with the approach and break the animation.
The library will warn you about the ones that are know to break the animation:
scroll-behavior: smooth
scroll-snap-type: x mandatory
(or y mandatory
depending on the axis you scroll)
Scrolling an iframe
You can also use the library to scroll iframes from the same domain (check MDN contentWindow documentation).
const iframeWindow =
document.querySelector('#my-iframe').contentWindow.document.documentElement;
animateScrollTo(500, {
elementToScroll: iframeWindow,
});
Please note: If the iframe is not on the same domain as the base page, you are going to get a cross origin error.
Why?
I wasn't able to find standalone, simple and working solution.
Browser support
Anything that supports requestAnimationFrame
and Promise
. For Internet Explorer you'll need to add es6-promise polyfill.
For IE9 and lower, you'll to provide requestAnimationFrame polyfill.
For IE8 and lower, you'll need to polyfill Array.forEach
as well. Haven't tested this though.
It is missing <insert a feature here>
I really tried to keep simple and lightweight.
If you are missing something, feel free to open a pull request.
Version 1
I advise you to use v2, as v1 is deprecated. But it is still available on v1 branch and on npm.