Library / SDK
janpaepke/ScrollMagic avatar
janpaepke/ScrollMagic

ScrollMagic 3: scroll position data without the animation layer

The javascript library for magical scroll interactions.

14,958 stars2,111 forksTypeScriptMIT

At a glance

What is it?
ScrollMagic 3 is a zero-dependency wrapper around IntersectionObserver and ResizeObserver that reports where an element sits relative to a scroll container. It ships as a beta on npm and deliberately does not animate anything.
Who is it for?
Adopt ScrollMagic 3 if you need progress values, enter/leave callbacks and a single observer pool across a page, and you are willing to pin to a 3.0.0 beta line. Do not adopt it as an animation engine: the README points at GSAP ScrollTrigger, Motion and anime.js for that, and ScrollMagic itself draws nothing.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What ScrollMagic 3 actually solves

The problem is not animation. It is knowing, cheaply and repeatedly, where an element sits relative to a scroll container. Doing that by hand means attaching a scroll listener, reading getBoundingClientRect on every frame, recomputing on resize, and handling the case where the element or the container changes size without a scroll event ever firing. That last case is what breaks naive implementations.

ScrollMagic 3 is a convenience wrapper around IntersectionObserver and ResizeObserver. The README describes it as handling "the performance pitfalls and counter-intuitive edge cases" of those two APIs. It reports a progress value from 0 to 1 and fires enter, leave and progress events. It does not animate. The README is explicit: "By itself, ScrollMagic doesn't animate anything."

The audience is therefore narrow and specific. It suits someone building a scroll progress bar, a parallax offset, a scroll-linked video scrubber, lazy loading, class toggles, or behavioural tracking, who wants the tracking layer solved and intends to write the visual layer themselves. It is framework agnostic, so React, Vue and vanilla JS projects are all in scope. It is not aimed at someone who wants a scroll animation to appear on screen with three lines of configuration.

Two bound pairs and the progress value they produce

The mechanism rests on two sets of bounds. Container bounds are a zone on the scroll container, set by containerStart and containerEnd. Element bounds are a zone on the tracked element, set by elementStart and elementEnd. Progress runs from 0 to 1 as the element bounds pass through the container bounds, and events fire on enter, leave and progress change.

The two configurations the README presents as mental models are contain and intersect. Contain is the default when element is null: containerStart and containerEnd are both at 'here' (0%), so progress advances while one box fully contains the other. Intersect is the default when element is set: containerStart and containerEnd sit at 'opposite' edges, so progress advances from the moment the element's leading edge enters the viewport until its trailing edge leaves.

The README states plainly that these are "useful mental models, not rigid modes". You can set containerStart: 0, containerEnd: 0 on an instance that has an element to get contain behaviour, or mix container and element insets for a custom tracking zone. If you already know CSS scroll-driven animations, the README maps the native view() ranges onto these settings: cover corresponds to the intersect default, contain to the contain default, entry to containerStart: 'opposite' with containerEnd: 0, and exit to containerStart: 0 with containerEnd: 'opposite'.

The performance claim is structural rather than measured in the README: shared observers, batched rAF and single-frame updates. That is a design statement about how many observers the library opens and when it writes, not a benchmark result.

Installing ScrollMagic 3 and wiring a first tracker

The package is published on npm under a next tag because the 3.x line is in beta. The README gives this install command:

bash
npm install scrollmagic@next

The package.json sets "type": "module" and declares an engines field of node >=18, so the toolchain expects a modern Node. The quick start in the README creates an instance, passes a selector as element, and chains three event handlers:

js
import ScrollMagic from 'scrollmagic';

new ScrollMagic({ element: '#my-element' })
	.on('enter', () => console.log('visible!'));

The README's own example also attaches a leave handler and a progress handler that reads e.target.progress and formats it as a percentage. Because element is set, this instance uses the intersect default: it fires enter when the element's leading edge meets the viewport and leave when the trailing edge departs.

If you would rather not route through the default export, package.json exposes a second entry point at scrollmagic/util with its own ESM and UMD builds and its own type declarations. The dist folder is the only thing the files field publishes, so anything you import comes from the built output rather than from src.

Where ScrollMagic 3 is the wrong tool

The clearest limitation is stated by the project itself. If you want a ready-made scroll animation, the README sends you elsewhere: GSAP ScrollTrigger, Motion, or anime.js. ScrollMagic will tell you that an element is 43 percent through its range. It will not move it, fade it, or pin it. Every visual decision is yours, which means the effort you save on observation bookkeeping you spend again on the animation layer.

The second constraint is release maturity. The recent tags are v3.0.0-beta.1, v3.0.0-beta.2 and v3.0.0-beta.3, and package.json carries version 3.0.0-beta.5. Anyone installing from the next tag is on a beta line, and the README's own comment block notes that the static shields for license, bundle and dependencies still need replacing once published. That is a small signal, but it tells you the documentation and packaging are still being tidied.

The third is a hard boundary rather than a defect. ScrollMagic is built for modern browsers, and the README positions it as complementing native scroll-driven animations, which it notes are not yet supported in all browsers. If your target is a browser without IntersectionObserver or ResizeObserver, the wrapper has nothing to wrap. The README does not document a polyfill path, and it does not document rollback behaviour for a partially applied state.

GSAP ScrollTrigger versus ScrollMagic 3: different jobs

The comparison worth making is with GSAP ScrollTrigger, because the README names it first among the alternatives. The difference is not quality, it is where the boundary sits.

ScrollTrigger is an animation plugin. You describe a tween and a trigger, and the plugin drives the tween as the scroll position changes. The animation and the scroll linkage arrive together. ScrollMagic ships the scroll linkage only: progress values, enter and leave events, and state management, with the README noting that native CSS scroll-driven animations do not cover cross-browser support, event callbacks, progress values or state management. That sentence is effectively the project's pitch against the native API, and it applies just as well against any animation library that hides its tracking internals.

So the choice follows from what you already have. If your visuals are CSS classes toggled at thresholds, or a canvas you drive yourself, or a video element whose currentTime you set, an animation library is overhead you do not need. If your visuals are tweens you would otherwise hand-write, ScrollTrigger removes work that ScrollMagic leaves in place. Note also the second entry point at scrollmagic/util, which suggests the maintainers expect some consumers to want the utility layer without the observer wrapper.

Licence, maintenance and the cost of staying on the beta line

ScrollMagic is MIT licensed, and the repository carries LICENSE.md at the top level. The README's badge links there. MIT imposes essentially no conditions beyond preserving the notice, but this is a description of the licence file, not legal advice; read LICENSE.md and your own organisation's policy before shipping.

The repository is not archived and the last push was on 2026-09-11, which is recent. The release cadence visible in the tag list is tighter than the version numbers suggest: three betas landed within roughly two days in February 2026, and package.json has since moved to 3.0.0-beta.5. That pattern points to active iteration on the 3.x line rather than a frozen project.

The upgrade cost is concentrated in one place. ScrollMagic v2 is a different API and lives on the v2-stable branch, which the README links from a note at the top. There is no migration guide in the README, so a v2 codebase moving to 3.x should treat the constructor options, the event names and the plugin system as things to verify against the README rather than assume. The repository does carry PLUGINS.md and MAINTAINING.md at the top level, which is where the extension surface is documented. The README states dependencies: 0, so there is no transitive dependency surface to audit.

Editorial conclusion

Adopt ScrollMagic 3 if you need progress values, enter/leave callbacks and a single observer pool across a page, and you are willing to pin to a 3.0.0 beta line. Do not adopt it as an animation engine: the README points at GSAP ScrollTrigger, Motion and anime.js for that, and ScrollMagic itself draws nothing. Before you commit, verify the published dist files and type declarations on npm under the next tag, and read the Options table in the README to confirm the containerStart and elementStart defaults match your layout.

Frequently asked questions

What is ScrollMagic?

ScrollMagic tells you where an element is relative to the viewport as the user scrolls, and fires events when that changes. It is a wrapper around IntersectionObserver and ResizeObserver, and it does not animate anything by itself.

What is a ScrollMagic alternative if I want ready-made scroll animations?

The README points to GSAP ScrollTrigger, Motion and anime.js for ready-made scroll animation solutions. It also mentions native CSS scroll-driven animations for pure CSS work, noting they are not yet supported in all browsers.

How do I install ScrollMagic 3?

The README gives the command npm install scrollmagic@next. The next tag is used because the 3.x line is still in beta, and package.json requires node >=18.

Does ScrollMagic 3 work with React or Vue?

The README describes the library as framework agnostic and says it works with React, Vue and vanilla JS. The constructor accepts a selector string or an Element for the element option.

What is the difference between contain and intersect in ScrollMagic 3?

Contain is the default when element is null, with containerStart and containerEnd both at 'here', so progress advances while one box fully contains the other. Intersect is the default when element is set, with the container bounds at 'opposite' edges, so progress advances while the element intersects the viewport.

Official sources

  1. janpaepke/ScrollMagic on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/janpaepke-scrollmagic.svg)](https://hysenlabs.com/projects/janpaepke-scrollmagic)