
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.
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.5moves at half scroll speed. Automatically disabled on touch devices unlessdata-scroll-enable-touch-speedis 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 withwindow.addEventListener(eventName, handler).data-scroll-css-progress: Add--progressCSS 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 withprogressvalue inevent.detail.data-scroll-to: Convert element into a scroll trigger. Useshrefattribute for links ordata-scroll-to-hreffor other elements. Prevents default click behavior.data-scroll-to-href(string): Target selector or position fordata-scroll-toaction. Example:'#section-3'.data-scroll-to-offset(number): Scroll padding top in pixels fordata-scroll-toaction. Example:100adds 100px offset from target.data-scroll-to-duration(number): Animation duration in seconds fordata-scroll-toaction. Example:2creates 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. Enablesdata-scroll-speedon 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 towindow.content(HTMLElement): The content element. Defaults todocument.documentElement.lerp(number): Linear interpolation intensity (0 to 1). Defaults to0.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 totrue.smoothTouch(boolean): Enables smooth scrolling for touch. Defaults tofalse.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 totrue.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:
- Lenis: This is the engine powering Locomotive Scroll. Use this if you only need smooth scrolling and want to build your own parallax logic.
- Rellax: A vanilla JavaScript library dedicated solely to parallax. It does not handle smooth scrolling.
- 10 Best Parallax Scrolling Effects In JavaScript
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.
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.
Discover more from RSS Feeds Cloud
Subscribe to get the latest posts sent to your email.
