ScrollMagic: JavaScript Scroll Interaction Library

File Size: 585 KB
Views Total: 24392
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
ScrollMagic: JavaScript Scroll Interaction Library

ScrollMagic is a framework-agnostic JavaScript library that tracks an element's position relative to a scroll container and reports entry, exit, and scroll progress changes.

The latest ScrollMagic 3 uses IntersectionObserver and ResizeObserver, requires no jQuery dependency, and leaves animation work to CSS or libraries such as GSAP, Motion, and anime.js.

Existing ScrollMagic 2 projects can keep the Controller and Scene API through the legacy v2 package, and v3 uses a new per-element API under the next npm tag.

Features

  • Element entry, exit, and scroll-progress tracking.
  • Vertical and horizontal scroll containers.
  • Window or custom element scroll containers.
  • Numeric, percentage, named, and function-based range offsets.
  • Per-instance progress, velocity, active-range, and resolved-bound values.
  • on, off, and subscribe event APIs.
  • Runtime option updates, bounds refresh, pause, resume, and destroy methods.
  • Plugin lifecycle hooks and native TypeScript definitions.

Use Cases

  • Scroll progress bars tied to a document or a page section.
  • Class toggles for reveal transitions when a section enters or leaves the viewport.
  • Parallax, video scrubbing, and storytelling sequences driven by a 0-to-1 progress value.
  • Lazy loading, analytics hooks, or content activation linked to viewport position.

How To Use ScrollMagic 3

Install The Current v3 Package

Use the next npm tag for ScrollMagic 3. 

npm install scrollmagic@next

Track An Element Entering And Leaving The Viewport

Import ScrollMagic, point the instance at one element, and bind the scroll state events you need.

<section id="feature-story">
  <h2>Product Story</h2>
  <p>Scroll to watch this content react to viewport changes.</p>
</section>
import ScrollMagic from 'scrollmagic';

var story = document.querySelector('#feature-story');

var tracker = new ScrollMagic({
  element: story
});

tracker
  .on('enter', function () {
    story.classList.add('is-active');
  })
  .on('leave', function () {
    story.classList.remove('is-active');
  });

Track Scroll Progress

The progress value runs from 0 to 1 across the configured active range. This value works for progress indicators, parallax transforms, video timelines, and other scroll-linked logic.

import ScrollMagic from 'scrollmagic';

var progressBar = document.querySelector('#story-progress');

new ScrollMagic({
  element: '#story-section'
}).on('progress', function (event) {
  progressBar.style.transform =
    'scaleX(' + event.target.progress + ')';
});

Define A Custom Tracking Zone

ScrollMagic uses element bounds and container bounds to calculate the active range. Named positions include here (0%), center (50%), and opposite (100%).

var tracker = new ScrollMagic({
  element: '#chapter',
  containerStart: 'center',
  containerEnd: 'center',
  elementStart: -50,
  elementEnd: -100
});

ScrollMagic 3 Options

Option Description
element Type: Element, String, or null. Tracks the element or first selector match. The default resolves to the first child of the container.
elementStart Type: Number, String, or Function. Default: 0. Sets the start inset on the tracked element.
elementEnd Type: Number, String, or Function. Default: 0. Sets the end inset on the tracked element.
container Type: Window, Element, String, or null. Default: window. Sets the scroll container or first selector match.
containerStart Type: Number, String, Function, or null. Its inferred value depends on the element option. Sets the start inset on the scroll container.
containerEnd Type: Number, String, Function, or null. Its inferred value depends on the element option. Sets the end inset on the scroll container.
vertical Type: Boolean. Default: true. Uses vertical tracking when true and horizontal tracking when false.

Events

Event Fires When
enter The element enters the active range and progress leaves an endpoint.
leave The element leaves the active range and progress reaches 0 or 1.
progress The progress value changes inside the active range.

Read Event Data

tracker.on('progress', function (event) {
  console.log(event.type);       // progress
  console.log(event.direction);  // forward or reverse
  console.log(event.location);   // start, inside, or end
  console.log(event.target.progress);
});

Instance Methods

Method Description
on(type, callback, options) Registers an event listener and returns the instance. The options object accepts once: true.
off(type, callback) Removes a registered event listener and returns the instance.
subscribe(type, callback, options) Registers a listener and returns an unsubscribe function.
modify(options) Updates multiple instance options in one call.
refresh() Recalculates cached bounds after external layout changes.
disable() Disconnects the tracking observers and freezes the current progress value.
enable() Reconnects tracking after disable() and recalculates the current state.
destroy() Destroys the instance and disconnects its observers.
addPlugin(plugin) Registers a plugin object on the instance.
removePlugin(plugin) Removes a plugin object and runs its removal hook.

Plugin Lifecycle Hooks

Hook Runs When
onAdd() addPlugin() registers the plugin.
onRemove() removePlugin() removes the plugin while the instance is active.
onEnable() enable() resumes tracking.
onDisable() disable() pauses tracking. It also runs before onDestroy() during destruction of an enabled instance.
onDestroy() destroy() tears down the instance.
onModify(changes) modify() or an option setter changes one or more public options.

State Properties

Property Description
progress Current progress from 0 to 1.
activeRange Container scroll positions for the start and end of the active range.
scrollVelocity Scroll velocity in pixels per second along the tracked axis.
resolvedBounds Cached element and container layout bounds.
disabled True after tracking is disabled or the instance is destroyed.
pluginList A snapshot of plugins registered on the instance.

Static Methods

Method Description
ScrollMagic.defaultOptions(options) Reads or changes defaults used by new instances.
ScrollMagic.refreshAll() Recalculates bounds for every active ScrollMagic instance.
ScrollMagic.destroyAll() Destroys every active ScrollMagic instance.

Update Multiple Options At Runtime

tracker.modify({
  containerStart: 'center',
  containerEnd: 'center',
  elementStart: '20%'
});

Refresh Bounds After Layout Changes

ResizeObserver handles element size changes, but some DOM and CSS updates move an element while its size stays unchanged. Call refresh() after these changes:

  • Margin, padding, or positioning changes that move the tracked element.
  • Class changes that alter page layout.
  • Sibling elements inserted or removed above the tracked element.
  • Images that load with no explicit dimensions.
  • Web fonts that shift document layout after loading.

Pinning Elements In ScrollMagic 3

ScrollMagic 3 has no setPin() method. Use CSS position: sticky for pinned sections. The v2 JavaScript pin system switches element positioning during scroll and can show a one-frame jump during fast scrolling. ScrollMagic 3 removes that subsystem.

.sticky-panel {
  position: sticky;
  top: 0;
}

Using ScrollMagic With Animation Code

ScrollMagic 3 reports state and progress but does not include the v2 GSAP or Velocity animation bridges. Feed event.target.progress into your animation code, or use enter and leave to change classes.

var card = document.querySelector('#scroll-card');

new ScrollMagic({
  element: card
}).on('progress', function (event) {
  var progress = event.target.progress;

  card.style.opacity = progress;
  card.style.transform =
    'translateY(' + ((1 - progress) * 40) + 'px)';
});

ScrollMagic 2 And jQuery Legacy Setup

ScrollMagic 2.0.9 is the final v2 release. Its Controller and Scene architecture is useful for existing projects that already depend on v2 plugins, scene pinning, or older ScrollMagic examples.

The v2 core does not require jQuery. The optional jquery.ScrollMagic.js plugin requires jQuery 1.11 or newer. It accepts jQuery objects and selectors where ScrollMagic expects DOM elements and exposes ScrollMagic through $.ScrollMagic.

Install ScrollMagic 2

npm install scrollmagic

A browser project can also load the v2 core from cdnjs.

<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.9/ScrollMagic.min.js"></script>

Legacy v2 Plugins

  • animation.gsap.min.js: Connects v2 scenes to GSAP tweens and timelines.
  • animation.velocity.min.js: Connects v2 scenes to Velocity animations.
  • debug.addIndicators.min.js: Displays scene trigger and duration indicators during development.
  • jquery.ScrollMagic.min.js: Adds jQuery object and selector handling to v2.

Basic ScrollMagic 2 Scene

var controller = new ScrollMagic.Controller();

var scene = new ScrollMagic.Scene({
  triggerElement: '#legacy-section',
  duration: 300,
  triggerHook: 'onCenter'
})
.setPin('#legacy-panel')
.addTo(controller);

ScrollMagic 2 To ScrollMagic 3 Reference

ScrollMagic 2 ScrollMagic 3
Controller + Scene One ScrollMagic instance for each tracked element.
triggerElement element.
triggerHook, offset, duration elementStart, elementEnd, containerStart, and containerEnd.
Scene lifecycle and progress events enter, leave, and progress on the instance.
setPin() CSS position: sticky.
animation.gsap.js Animation code reads ScrollMagic state or progress directly.
jquery.ScrollMagic.js No jQuery plugin in v3.
debug.addIndicators.js No indicator plugin in the v3 core package.

 

Alternatives And Related Resources

FAQs

Q: Does ScrollMagic require jQuery?
A: No. ScrollMagic 3 has no jQuery dependency, and the ScrollMagic 2 core has been dependency-free since v2. The old jquery.ScrollMagic.js file is an optional v2 integration plugin.

Q: Why does npm install scrollmagic install ScrollMagic 2?
A: The default npm package points to the final v2 release. Install ScrollMagic 3 from the next tag with npm install scrollmagic@next.

Q: Can I use setPin() in ScrollMagic 3?
A: No. ScrollMagic 3 removed the JavaScript pin system. Use CSS position: sticky for pinned sections.

Q: Can ScrollMagic 3 work with GSAP?
A: Yes. ScrollMagic 3 exposes scroll state and progress that animation code can read. It does not include the v2 animation.gsap.js bridge.

Q: My tracked element moved after a layout update. What should I call?
A: Call instance.refresh() after layout changes that move the element but do not resize it. Use ScrollMagic.refreshAll() when several instances need new bounds.

Changelog:

v3.0.0beta (2026-09-03)

  • Update ScrollMagic v3

v2.0.9 (2026-02-22)

  • Final v2 release
  • ScrollMagic v3 is coming soon

v2.0.8 (2020-08-15)

  • Added support for GSAP JavaScript animation library 3.

v2.0.7 (2019-05-07)

  • Fixed error in Safari when using setPin
  • Added missing semi-colon to isMobile regex
  • Fixed SVG element detection as Dom Element and related Error on Safari
  • Fixed code selection in examples
  • Pass Scene as this to duration callback
  • Increase fps limit for mobile support(advance) example.
  • Added documentation for responsive duration (e.g. "100%")
  • Updated Section Wipes (natural) to work for large number of sections.
  • Removed warning for pushFollowers in pins with duration 0, unless actively set to true.
  • Fixed some spelling stuff.

v2.0.6 (2018-10-20)

  • Bugfixes

v2.0.5 (2015-04-30)

  • Fixed: a JS error occurred in IE9 see here
  • Fixed: cascading pins of absolutely positioned elements didn't work see here
  • Fixed: scene state wasn't correct at start position see here
  • Fixed: updatePinState was called before scrollOffset update

v2.0.4 (2015-04-08)

  • fixed JS error in IE9

v2.0.0 (2015-02-26)

  • removal of all dependencies (jQuery & GSAP) – ScrollMagic is now stand-alone.
  • new file structure
  • new scene event: add fires when scene is added to a controller
  • new scene event: remove fires when scene is removed from a controller
  • option changes in Scene.addIndicators()
  • several performance tweaks
  • lots more info and warning messages (in the uncompressed development version)

v1.3.0 (2014-11-13)

  • changed AMD loader behavior to export only one object -> {Controller: ScrollMagic, Scene: ScrollScene}
  • added Error message for missing dependencies
  • fixed bubbling of pseudo-resize event of div containers
  • reference bug with AMD loading

v1.2.3 (2014-10-25)

  • fixed: reference bug when using asynchronous loading

v1.2.2 (2014-10-21)

  • fixed: Error message with wrong loading order

v1.2.0 (2014-10-16)

  • AMD loader support
  • added warning for tweens being overwritten
  • better code for mobile clicks 
  • updated draw example to camel case to support Firefox
  • updated parralax sections example to moving divs instead of background position
  • added new references
  • added favicon
  • scroll momentum increased in Firefox over fixed elements 
  • parallax example was juggy in Firefox and Safari -> removed reliance of TweenMax ticker in favor of requestAnimationFrame 
  • bugfix for pinned elements jittering if inside a container, because of the delayed position update in refreshInterval
  • bugfix: div resize event bubbled up to window

v1.1.2 (2014-09-16)

  • fixed a bug with the scrollTo method

v1.1.1 (2014-09-04)

  • Major update.

v1.0.9 (2014-08-19)

  • added new feature `ScrollMagic.scrollTo()`

v1.0.8 (2014-05-27)

  • Feature: add class for pinned element during pin

v1.0.7 (2014-04-15)

  • feature: ScrollScene.startOffset

v1.0.6 (2014-04-05)

  • fixed a bug concerning relative sizing of pinned elements

v1.0.5 (2014-03-24)

  • updates.

This awesome jQuery plugin is developed by janpaepke. For more Advanced Usages, please check the demo page or visit the official website.