A tiny JavaScript library to enable CSS animations when user scrolls.

This library allows you to toggle one or more classes on an element when it appears inside the viewport when the user scrolls the page. It enables you to build CSS transitions or animations launched only when the user scrolls the page to the element. All you have to do is set a few HTML attributes, and code the rest with your CSS skills.


The following fake elements are randomly generated, only to illustrate what you can do with this library.

The circles are set to be animated several or infinite times, the squares just once. Of course, the animations defined manually are only for example. You can make whatever you want in your CSS.

Hover over any of them to see their settings in the tooltip. If you want to follow one when you scroll up and down the page, just click on it.

Quick start


Then, add the script into your page:

<script src="./your-path/onscroll-effect.es6.min.js"></script>

and it’s done.

With npm

Install with npm:

npm install onscroll-effect

Then import onScroll Effect into your application, inside your main JS file:

import "onscroll-effect";

and the magic happens!


In addition of using ES5 version, compatibility for Internet Explorer is provided by polyfill.io which supports back to IE 7. And before you ask, yes, you can run it locally.

How to use

Note that as default behaviour, this library add a class list when the element is outside of the viewport.

That is in order to avoid a broken page if your JavaScript is in error. This way, if you have any JavaScript issue, the default state of your element will appears on scroll.

Sometimes, you may need the opposite behaviour, i.e. adding a class when the element is inside the viewport. There is an option for that.


<foo data-scroll="class">

required — A CSS class or list, added when this element is outside of the viewport.

You can fill it from none to as many classes as you want, so it's compatible with any CSS framework.
If you leave it empty, the class is-outside will be used by default.

<foo data-scroll data-scroll-repeat=" false | true | <number> ">

optional — Specify if the class will be toggled each time the element appears in the viewport, or not, or a maximum number of iteration.

If unset or left empty, false by default.

<foo data-scroll data-scroll-offset=" <number> ">

optional — Specify an offset, in pixels, to take into account from the top and bottom edges of the viewport.

If unset or left empty, 0 by default.

<foo data-scroll data-scroll-reverse="true">

optional — Instead of adding the class list when the element is outside of the viewport, reverse this behaviour and add the class when the element comes inside the viewport.

If the attribute data-scroll is left empty, the class is-inside will be used by default.

In this case, you will probably need to add the class by default onto your element in your code to avoid JavaScript dependency.

Examples of use

<!-- Toggle '.is-outside' class when outside of viewport, just once -->
<div data-scroll> … </div>

<!-- Toggle '.mulder' class when outside of viewport, just once -->
<div data-scroll="mulder"> … </div>

<!-- Toggle '.scully' class each time when outside of viewport -->
<div data-scroll="scully" data-scroll-repeat="true"> … </div>

<!-- Toggle '.alien' class 10 times when outside of 100 pixels
     of top and bottom edges of viewport -->
<div data-scroll="alien" data-scroll-repeat="10" data-scroll-offset="100"> … </div>


Most of the time, when you build a transition or an animation on an element, you don’t need it to be played backward when this element goes outside of the viewport. That’s why I recommend to use these few lines of CSS:

[data-scroll].is-outside {
	transition: none;
	animation: none;


Custom prefix

You can change the prefix scroll in data-scroll and every attributes to prevent conflict with another JS library. To do so, add this attribute to your <html> element with your new prefix:

<html data-onscroll-effect-custom-prefix="my-prefix">

It will so be set to all attributes like data-my-prefix.



The scroll event handler: initialize all elements to be ready to animate on scroll.


No parameter. No return.


Get if an element is currently inside the viewport, taking into account the set offset.

window.onScrollEffect.isInsideViewport( Node );

Takes a Node as parameter. Returns a Boolean.


Get if an element is still repeating its animation on scroll.

window.onScrollEffect.isRepeating( Node );

Takes a Node as parameter. Returns a Boolean.


Get the count of animation iteration already made by an element.

window.onScrollEffect.repeatingCount( Node );

Takes a Node as parameter. Returns a Number.


You can also add some hooks: each element with data-scroll attribute fires an insideViewport event when it appears in viewport, and an outsideViewport event when it disappears from viewport, so You can add event listeners on these events.

For example:

document.querySelector("#myElement").addEventListener("insideViewport", (event) => {
	console.log(`Count: ${window.onScrollEffect.repeatingCount(event.target}`);
}, false);