Categories: CSSScriptWeb Design

Animate Elements On Scroll With Parallax Effect – locomotive-scroll

locomotive-scroll is a modern JS library that applies a smooth, subtle, configurable smooth scroll & parallax scroll effect to elements when scrolled into view.

Version 5 represents a complete rewrite from previous versions. The library now uses dual Intersection Observer strategies to optimize performance. Simple viewport triggers use one observer while continuous animations like parallax use a separate RAF-based observer.

Sponsored

This separation reduces unnecessary computation. locomotive-scroll automatically disables parallax on touch devices to preserve native scrolling performance. Custom scroll containers are now supported alongside the default full-page scrolling mode.

Features:

  • Dual Intersection Observer Architecture: Separates simple viewport triggers from continuous RAF-based animations.
  • Lenis-powered: Built on Lenis library for smooth scrolling with configurable easing, lerp intensity, and duration controls.
  • TypeScript Support: Fully typed API with interface definitions for all configuration options and method signatures.
  • Automatic Touch Detection: Disables parallax effects on devices with touch capability to maintain native scroll performance.
  • Custom Scroll Containers: Supports both full-page scrolling and constrained container scrolling with synchronized ResizeObserver handling.
  • Zero Layout Shift: Avoids CSS transform conflicts that break layouts by using non-greedy positioning strategies.
  • Progressive Enhancement: Elements only subscribe to requestAnimationFrame when visible and actively animating.
  • Flexible Progress Tracking: Exposes scroll progress as CSS custom properties or JavaScript events for scroll-driven animations.

Use Cases:

  • Portfolio Websites with Parallax: Implement depth effects on hero sections and project showcases where background layers move at different speeds during scroll.
  • Product Landing Pages: Trigger animations and state changes when feature sections enter the viewport to create guided scrolling experiences.
  • Long-Form Editorial Content: Add scroll progress indicators and section-based animations to improve readability on article pages.
  • Interactive Storytelling: Build narrative-driven experiences where content reveals and transforms based on scroll position and velocity.

How to use it:

1. Install the package and import the LocomotiveScroll module.

# NPM
$ npm install locomotive-scroll --save
import LocomotiveScroll from 'locomotive-scroll';
@import 'locomotive-scroll/dist/locomotive-scroll.css';

2. Or load the necessary JavaScript & CSS files from the bundled folder.

<script src="bundled/locomotive-scroll.min.js"></script>
<link href="bundled/locomotive-scroll.css" rel="stylesheet" />

3. Initialize the LocomotiveScroll with default settings.

const myScroll = new LocomotiveScroll();

4. Apply the LocomotiveScroll to target elements using the data-scroll attribute:

<div data-scroll>Element To Animate</div>

5. Config the parallax scroll effect with the following data attributes:

  • data-scroll: Enable viewport detection and scroll observation on the element. Required for all scroll-based features.
  • data-scroll-speed (number): Set parallax speed relative to scroll container size. Positive values move slower than scroll. Negative values reverse direction. Example: 0.5 moves at half scroll speed. Automatically disabled on touch devices unless data-scroll-enable-touch-speed is present.
  • data-scroll-position (string): Define trigger positions for viewport detection. Format: 'element_position, viewport_position'. Values: 'start', 'middle', 'end'. Example: 'start, middle' triggers when element’s top edge reaches viewport center. Default: 'start, end'.
  • data-scroll-offset (string): Add pixel or percentage offset to trigger points. Format: 'enter_offset, leave_offset'. Example: '200, 100' triggers 200px before entry and 100px before exit. Percentages are relative to viewport height. Default: '0, 0'.
  • data-scroll-class (string): Class name to apply when element is in viewport. Default: 'is-inview'.
  • data-scroll-repeat: Allow class and events to retrigger on each viewport entry. Without this attribute, triggers fire only once.
  • data-scroll-call (string): Custom event name to dispatch when element enters or leaves viewport. Listen with window.addEventListener(eventName, handler).
  • data-scroll-css-progress: Add --progress CSS custom property to the element. Value ranges from 0 to 1 as element moves through viewport.
  • data-scroll-event-progress (string): Custom event name for progress updates. Fires continuously with progress value in event.detail.
  • data-scroll-to: Convert element into a scroll trigger. Uses href attribute for links or data-scroll-to-href for other elements. Prevents default click behavior.
  • data-scroll-to-href (string): Target selector or position for data-scroll-to action. Example: '#section-3'.
  • data-scroll-to-offset (number): Scroll padding top in pixels for data-scroll-to action. Example: 100 adds 100px offset from target.
  • data-scroll-to-duration (number): Animation duration in seconds for data-scroll-to action. Example: 2 creates a 2-second scroll animation.
  • data-scroll-ignore-fold: Prevent automatic offset adjustment for elements visible in the initial viewport. By default, in-fold elements start their progress from their initial position.
  • data-scroll-enable-touch-speed: Override the automatic parallax disabling on touch devices. Enables data-scroll-speed on mobile and tablets. Use carefully as this may impact scroll performance.
<div data-scroll
     data-scroll-speed="1">
     data-scroll-call="EVENT_NAME"
     >
     Element To Animate
</div>

6. All possible settings to config the library.

  • lenisOptions (object): Configures the underlying Lenis instance.
    • wrapper (HTMLElement|Window): The scroll container. Defaults to window.
    • content (HTMLElement): The content element. Defaults to document.documentElement.
    • lerp (number): Linear interpolation intensity (0 to 1). Defaults to 0.1.
    • duration (number): Animation duration.
    • orientation (string): ‘vertical’ or ‘horizontal’.
    • gestureOrientation (string): ‘vertical’, ‘horizontal’, or ‘both’.
    • smoothWheel (boolean): Enables smooth scrolling for mouse wheel. Defaults to true.
    • smoothTouch (boolean): Enables smooth scrolling for touch. Defaults to false.
    • wheelMultiplier (number): Multiplier for mouse wheel events.
    • touchMultiplier (number): Multiplier for touch events.
    • normalizeWheel (boolean): Normalizes wheel inputs across browsers.
    • easing (function): Custom easing function.
  • triggerRootMargin (string): Root margin for IntersectionObserver triggers. Defaults to '-1px -1px -1px -1px'.
  • rafRootMargin (string): Root margin for RAF-based updates. Defaults to '100% 100% 100% 100%'.
  • autoStart (boolean): Starts the RAF loop automatically. Defaults to true.
  • scrollCallback (function): Callback returning scroll object { scroll, limit, velocity, direction, progress }.
  • initCustomTicker (function): Callback to initialize an external ticker (like GSAP).
  • destroyCustomTicker (function): Callback to destroy the external ticker.
const myScroll = new LocomotiveScroll({
  lenisOptions: {
    // ...
  },
  // more options here
});

7. API methods.

// Stop the scroll animation loop
// Useful when pausing scroll interactions during modals or overlays
myScroll.stop();

// Resume the scroll animation loop
// Call after stopping to re-enable scroll
myScroll.start();

// Manually trigger resize recalculation
// Rarely needed since Lenis handles ResizeObserver internally
myScroll.resize();

// Destroy the Locomotive Scroll instance and remove all event listeners
// Call when unmounting components or cleaning up instances
myScroll.destroy();

// Scroll to a target element, position, or keyword
// target: HTMLElement, number (position), or string ('top', 'bottom', CSS selector)
// options: object with offset, duration, easing, immediate, lock, force, onComplete
myScroll.scrollTo(target, options);

// Add scroll observation to newly inserted DOM elements
// newContainer: HTMLElement containing new [data-scroll] elements
myScroll.addScrollElements(newContainer);

// Remove scroll observation from DOM elements about to be removed
// oldContainer: HTMLElement containing [data-scroll] elements to unobserve
myScroll.removeScrollElements(oldContainer);

8. Event handlers.

// Fired on each scroll frame when scrollCallback is configured
// Provides scroll position, velocity, direction, and progress data
scroll = new LocomotiveScroll({
  scrollCallback: ({ scroll, limit, velocity, direction, progress }) => {
    console.log('Scroll data:', { scroll, limit, velocity, direction, progress });
  }
});

// Custom viewport trigger event (configured via data-scroll-call attribute)
// Fired when element enters or leaves viewport
window.addEventListener('yourCustomEvent', (e) => {
  const { target, way, from } = e.detail;
  // target: the element that triggered the event
  // way: 'enter' or 'leave'
  // from: 'start' or 'end' (which edge triggered)
  console.log(`Element ${way} viewport from ${from}`);
});

// Custom progress event (configured via data-scroll-event-progress attribute)
// Fired continuously as element moves through viewport
window.addEventListener('yourProgressEvent', (e) => {
  const { target, progress } = e.detail;
  // progress: 0 to 1 representing element's position in viewport
  console.log(`Element progress: ${progress}`);
});

Alternatives:

FAQs:

Q: Does it work on mobile devices?
A: Yes. However, the library automatically disables the parallax effect (data-scroll-speed) on touch devices. This preserves the native scroll feel and performance. You can force it on by adding the data-scroll-enable-touch-speed attribute.

Q: Can I use it with React or Vue?
A: Yes. You should initialize the instance inside a useEffect (React) or onMounted (Vue) hook. Remember to call .destroy() in the cleanup function to prevent memory leaks.

Q: How do I handle dynamic content loaded via AJAX?
A: You must tell the instance about the new content. Use the addScrollElements($container) method after the new DOM elements are injected.

Sponsored

Q: Why isn’t my fixed header working?
A: Version 5 supports position: fixed natively because it no longer uses a transform wrapper for the whole page. If you use a custom container, verify your CSS context.

Changelog:

v5.0.1 (01/15/2026)

  • Version 5 is a complete rewrite of Locomotive Scroll, now built on top of Lenis.
  • Updated doc

v4.1.4 (05/03/2022)

  • Prevent keyboard scrolling depending on activeElement type

v4.1.3 (10/21/2021)

  • Fix scrollbar locks after scrolling with mousewheel.

v4.1.0 (02/19/2021)

  • Update

v4.0.3 (11/17/2020)

  • Update

v4.0.1 (11/16/2020)

  • Add horizontal scrolling
  • Update export to only import the native Class
  • Update scrollTo parameters with the options object (offset, duration, easing…)
  • Add context system to set specific options for desktop , tablet and mobile separately
  • Rewrite the instance options
  • Add data-scroll-id=”” attribute to select elements
  • Add currents “in view” elements as object in the on scroll event.
  • Add a progress value from 0 to 1, while the element is in the viewport

v3.6.1 (10/15/2020)

  • Fix moveScrollBar calculations

v3.5.0 (05/28/2020)

  • Add scrollFromAnywhere option
  • Add multiplier option
  • Rename inertia option to lerp
  • Bugs fixed

v3.1.8 (11/30/2019)

  • Fix safari polyfill

The post Animate Elements On Scroll With Parallax Effect – locomotive-scroll appeared first on CSS Script.

rssfeeds-admin

Share
Published by
rssfeeds-admin

Recent Posts

Zoom Update Scam Infected 1,437 Users to Deploy Surveillance Tools in 12 Days

A cleverly crafted fake Zoom website has silently pushed surveillance software onto Windows machines, infecting…

12 minutes ago

1Campaign Platform Helps Attackers Bypass Google Ads Screening to Show Malicious Ads

A newly uncovered cloaking platform called 1Campaign is giving cybercriminals a powerful tool to push malicious advertisements…

12 minutes ago

The Ultra Slim Lisen 5,000Mah Qi2-Certified Wireless Magnetic Power Bank Drops to $16.99

Apple iPhone users, check out this new deal on an ultra-slim MagSafe power bank that…

21 minutes ago

IGN Live Returns June 6 and 7 2026

IGN Live is back for another year, this year taking place June 6-7 in downtown…

22 minutes ago

New and Exclusive Clip From One Piece Season 2 | IGN Fan Fest 2026

One Piece Season 2 arrives on Netflix on March 10 at 12:00am PDT, and IGN…

22 minutes ago

Qualcomm won’t be announcing Windows gaming handhelds at GDC after all

In January, Qualcomm hinted to The Verge that it might finally bring its powerful Arm-based…

57 minutes ago

This website uses cookies.