
React Scroll Animation in Framer Motion: The Ultimate Guide (2026)
Key Takeaways
A react scroll animation in Framer Motion can be categorized into two primary types: scroll-triggered (fires when entering the viewport) and scroll-linked (tied dynamically to scroll progress).
You can trigger standard viewport animations effortlessly using the
whileInViewprop, avoiding complex boilerplateIntersectionObservercode.To create a dynamic framer motion scroll animation, leverage the
useScrollanduseTransformhooks to seamlessly map the user's scroll progression to CSS properties likescaleX,y, orclipPath.Framer Motion runs scroll-linked animations on the browser's native
ScrollTimelinewhen possible, ensuring hardware-accelerated animations that don't block the main thread.Premium react animations drastically increase user engagement and time-on-page, making them a crucial asset for SaaS owners looking to boost conversion rates.
You can skip the boilerplate entirely and get production-ready scroll animations by using pre-built components from ogblocks.
Let's face it: getting users to stay on your website is harder than ever. As developers and SaaS owners, we're constantly battling against shrinking attention spans. If your landing page looks like a static PDF from 2010, your bounce rate is probably going through the roof.
The solution? Motion. Specifically, a beautifully crafted react scroll animation in Framer Motion.
Adding premium react animations to your application doesn't just make it "look cool." It creates a narrative flow. It guides the user's eye down the page, softly presenting features and pricing options in a way that feels dynamic and premium.
According to research gathered by The Hoop Studio, the impact of web animation is undeniable:
- First Impressions Matter: Websites have less than 50 milliseconds to make an impact. Animations grab attention and keep users engaged.
- Boost Engagement: Animated content holds users’ attention 88% longer than static pages, giving you more time to communicate your message.
- Higher Conversions: Adding animations to landing pages can boost website conversion rates by over 80%, while animated call-to-action buttons boost click-through rates by 15%.
In this comprehensive, deep-dive guide, we are going to explore everything you need to know about building react scroll animations in 2026. We will look at both scroll-triggered and scroll-linked animations, break down code examples component-by-component, analyze performance impacts, compare Framer Motion to other libraries, and show you how you can save hundreds of hours by grabbing premium UI components from our library, ogblocks.
By the end of this over 2,000-word tutorial, you will be a master at creating mesmerizing scrolling experiences. Let's get moving!
💡 Expert Tip: When building SaaS dashboards, always restrict scroll-linked parallax to safe CSS transform properties (x, y, scale) to keep the main UI thread free and avoid dropping below 60fps.
What is Framer Motion and Why Use It?
Before we start writing code, let's briefly discuss why Framer Motion is the absolute king of react animations.
Framer Motion is a production-ready, declarative animation library for React. Unlike traditional CSS transitions or older libraries that require you to manually calculate DOM node positions, Framer Motion provides an incredibly intuitive, prop-driven API.
Why is it the best for SaaS owners and Developers?
- Developer Experience (DX): The API is entirely declarative. You don't have to write messy
refsor manually instantiate timelines. You just addanimate={{ opacity: 1 }}and it works. - Performance: As of the latest iterations in 2026, motion (the underlying engine) utilizes hardware-accelerated CSS transforms and native Browser APIs like
ScrollTimelineto make sure your animations hit 60-120fps without locking up the UI thread. - Complex Gestures Simplified: Dragging, tapping, panning, and hovering are all supported out-of-the-box.
- Scroll Specific APIs: It ships with dedicated React hooks specifically designed for intercepting and manipulating scroll paths.
If your goal is to make your SaaS product look like a $10M ARR company, Framer Motion is the tool you need.
Two Types of React Scroll Animations
When developers talk about building a react scroll animation in Framer Motion, they are usually referring to one of two distinct categories. It is critical to understand the difference between these two, as they require entirely different APIs and serve different user experience (UX) goals.
1. Scroll-Triggered Animations
A scroll-triggered animation is an animation that "fires" or starts playing the moment an element enters or leaves the browser's viewport.
- Example: You scroll down the page, and the pricing cards smoothly fade in and slide up.
- Under the Hood: Framer Motion uses a pooled
IntersectionObserverto efficiently monitor when elements cross the threshold of the screen.
2. Scroll-Linked Animations
A scroll-linked animation ties the actual value of an animation directly to the user's scroll position. If the user stops scrolling, the animation stops. If they scroll backward, the animation reverses.
- Example: A reading progress bar at the top of the screen that fills up as you scroll down, or a parallax background where mountains move slower than the trees in the foreground.
- Under the Hood: Framer Motion captures the scroll offset values via the
useScrollhook and maps them to CSS properties.
Now that we understand the distinction, let's dive into the code and see how to implement both types.
Setting Up Your React Environment
Before we can build any animations, we need to set up our project. Whether you are using Next.js (App Router or Pages Router), Vite, or standard Create React App, the installation process is straightforward.
Run the following command in your terminal:
npm install motion# ORyarn add motion# ORpnpm add motion
Note: In 2026, the package is now heavily unified under motion and accessed via motion/react, replacing the older framer-motion legacy imports for highly optimized bundles.
Once installed, we are ready to start animating.
Chapter 1: Building Scroll-Triggered Animations
For the vast majority of SaaS landing pages and developer portfolios, scroll-triggered animations are your bread and butter. You want your text and images to reveal themselves gracefully as the user scrolls.
Framer Motion makes this incredibly easy with the whileInView prop.
The Basics of whileInView
The whileInView prop acts just like the animate prop, except the animation only executes when the element visually enters the viewport.
Let's look at a basic fade-in and slide-up component:
import { motion } from "motion/react";export function PremiumFeatureCard() {return (<motion.divinitial={{ opacity: 0, y: 50 }}whileInView={{ opacity: 1, y: 0 }}transition={{ duration: 0.6, ease: "easeOut" }}className="p-6 bg-white rounded-2xl shadow-lg border border-gray-100"><h3 className="text-2xl font-bold">Lightning Fast Analytics</h3><p className="text-gray-600 mt-2">Understand your users in real-time with our completely revamped dashboard.</p></motion.div>);}
Lightning Fast Analytics
Understand your users in real-time with our completely revamped dashboard.
What is happening here?
initial: When the component first mounts (even hidden offscreen), it is completely transparent (opacity: 0) and pushed down 50 pixels (y: 50).whileInView: As soon as the browser detects the element is visible on the screen, Framer Motion animates it to full opacity (opacity: 1) and its natural vertical position (y: 0).transition: We define the duration (0.6 seconds) and use aneaseOutcurve for a smooth deceleration at the end of the movement.
Animating Only Once on Scroll
By default, the whileInView animation works dynamically in both directions. If you scroll past the element and then scroll back up, the animation will play again.
While this can be cool, it is often distracting on professional SaaS websites. Usually, you only want the entry animation to play the very first time the user sees it. To achieve this, we use the viewport prop.
<motion.divinitial={{ opacity: 0, scale: 0.9 }}whileInView={{ opacity: 1, scale: 1 }}viewport={{ once: true, amount: 0.3 }}transition={{ duration: 0.5 }}><img src="/dashboard-preview.png" alt="SaaS Dashboard" /></motion.div>
Understanding the viewport prop:
once: true: Tells Framer Motion to unobserve the element after the animation fires. It won't repeat if the user scrolls away and comes back.amount: 0.3: This is a crucial detail for developer experience. Settingamountto 0.3 means the animation will not trigger until at least 30% of the element is visible in the viewport. This prevents animations from firing when the element is barely peeking over the bottom edge of the screen, ensuring the user actually sees the beautiful motion.
Changing the Scroll Container
By default, whileInView observes the main window scroll. But what if you have a scrollable side-panel, a modal, or an overflow container?
You can set a custom scroll container using React's useRef and passing it to the root property of the viewport object.
import { useRef } from "react";import { motion } from "motion/react";export function ScrollableModal() {const containerRef = useRef(null);return (<divref={containerRef}className="h-[400px] overflow-y-scroll border-2 border-dashed border-gray-300 p-8"><div className="h-[600px] flex items-end"><motion.divinitial={{ opacity: 0 }}whileInView={{ opacity: 1 }}viewport={{ root: containerRef }}className="p-4 bg-blue-500 text-white rounded-lg">I fade in only when scrolling inside the modal!</motion.div></div></div>);}
Advanced Triggering: Using useInView for State Management
Sometimes you don't just want to animate CSS properties. Maybe you want to trigger a data fetch, play a video, or change a global React state when a block scrolls into view. For this, Framer Motion provides the useInView hook.
import { useRef, useEffect } from "react";import { useInView } from "motion/react";export function VideoAutoplayer() {const ref = useRef(null);// Track if the element is in viewconst isInView = useInView(ref, { amount: 0.5 });const videoRef = useRef(null);useEffect(() => {if (isInView && videoRef.current) {videoRef.current.play();} else if (!isInView && videoRef.current) {videoRef.current.pause();}}, [isInView]);return (<div ref={ref} className="w-full max-w-2xl mx-auto my-32 rounded-xl overflow-hidden shadow-2xl"><video ref={videoRef} src="/product-demo.mp4" loop muted playsInline /><div className="p-4 text-center text-sm text-gray-500">{isInView ? "Video Playing" : "Video Paused"}</div></div>);}
This is an incredibly powerful technique for optimizing your site's performance. By pairing useInView with heavy media elements, you ensure the browser isn't wasting CPU cycles decoding a video that the user can't even see.
Chapter 2: Scroll-Linked Animations with useScroll
While scroll-triggered animations are great for simple block reveals, if you want a react scroll animation in Framer Motion that drops jaws, you want to use scroll-linked animations.
These animations are tied mathematically to the scroll position. To achieve this, Framer Motion gives us the useScroll hook, alongside the useTransform hook.
What is useScroll?
At its core, useScroll returns a series of MotionValues (Framer Motion's optimized reactive state variables) that update whenever the user scrolls. The most commonly used value is scrollYProgress, which outputs a number between 0 (top of the page) and 1 (bottom of the page).
Let's look at the most classic implementation:
Building a Reading Progress Bar
A reading progress bar at the top of a blog post provides excellent UX. It tells your users exactly how much content is left. Let's build a fully reactive one.
import { motion, useScroll, useSpring } from "motion/react";export function ReadingProgress() {// Extract overall window scroll progress (0 to 1)const { scrollYProgress } = useScroll();// Optional but recommended: Apply a spring physics layer to smooth out the scrollconst scaleX = useSpring(scrollYProgress, {stiffness: 100,damping: 30,restDelta: 0.001});return (<motion.divstyle={{scaleX, // Link the mapped progress strictly to the X scalingoriginX: 0, // Ensure it scales from left-to-right, not from the center!}}className="fixed top-0 left-0 right-0 h-2 bg-indigo-600 z-50 origin-left"/>);}
With less than 20 lines of code, we've created a hardware-accelerated, butter-smooth progress bar.
The Image Reveal Effect using clipPath
One of the most premium, high-end design trends right now involves an image starting out heavily cropped or squeezed, and then "expanding" to full size as you scroll the page to center it. We can accomplish this by interpolating scrollYProgress against CSS clipPath parameters.
For this specific effect, we don't want the scrollYProgress of the entire page. We only care about the scroll progress of the image relative to the viewport.
import { useRef } from "react";import { motion, useScroll, useTransform } from "motion/react";export function DynamicImageReveal() {const containerRef = useRef(null);// Track this specific container instead of the whole windowconst { scrollYProgress } = useScroll({target: containerRef,// Start tracking when the top of the element hits the bottom of the viewport// Stop tracking when the center of the element hits the center of the viewportoffset: ["start end", "center center"]});// Transform the progress (0 to 1) into a CSS clip-path rule// 0 = aggressively cropped, 1 = uncropped (full image)const clipPath = useTransform(scrollYProgress,[0, 1],["inset(20% 40% 20% 40% round 30px)", "inset(0% 0% 0% 0% round 12px)"]);return (<motion.div ref={containerRef} className="py-screen-height flex justify-center mt-32"><motion.div style={{ clipPath }} className="w-full max-w-4xl shadow-2xl"><imgsrc="https://images.unsplash.com/photo-1551288049-bebda4e38f71?q=80&w=2070"alt="Data Dashboard"className="w-full h-auto object-cover"/></motion.div></motion.div>);}
Revealed!
This is how award-winning agency websites are built. Instead of letting images load abruptly, you tie their geometry to the user's scroll wheel, creating a deeply satisfactory, tactile feeling.
Horizontal Text Marquees on Vertical Scroll
Another incredibly popular trend in modern web design is the "horizontal text scroll." The user scrolls down vertically, but huge typography slides left or right across the screen in response.
This involves intercepting vertical scroll and piping it into the x CSS translation vector.
import { useRef } from "react";import { motion, useScroll, useTransform } from "motion/react";export function TextMarqueeScroll() {const containerRef = useRef(null);const { scrollYProgress } = useScroll({target: containerRef,offset: ["start end", "end start"]});const xRight = useTransform(scrollYProgress, [0, 1], ["-20%", "20%"]);const xLeft = useTransform(scrollYProgress, [0, 1], ["20%", "-20%"]);return (<div ref={containerRef} className="py-40 bg-white overflow-hidden flex flex-col gap-8"><motion.div style={{ x: xRight }} className="whitespace-nowrap"><h2 className="text-[10vw] font-black uppercase text-neutral-100 leading-none tracking-tighter mix-blend-difference">Premium React UI Components</h2></motion.div><motion.div style={{ x: xLeft }} className="whitespace-nowrap"><h2 className="text-[10vw] font-black uppercase text-indigo-600 leading-none tracking-tighter">Built with Framer Motion</h2></motion.div></div>);}
Premium React UI Components
Premium React UI Components
Premium React UI Components
Premium React UI Components
Premium React UI Components
Premium React UI Components
Built with Framer Motion
Built with Framer Motion
Built with Framer Motion
Built with Framer Motion
Built with Framer Motion
Built with Framer Motion
Performance Deep-Dive: Are React Scroll Animations Fast?
By now, you've seen how immensely powerful a react scroll animation in Framer Motion can be. But as a responsible developer or SaaS owner, you are probably asking the golden question: Will this slow down my site and ruin my Core Web Vitals?
The short answer is No. The long answer requires unpacking how Framer Motion handles rendering.
The Problem with Traditional Scroll Handlers
Back in the jQuery era, creating scroll animations required attaching a listener to window.onscroll. Every single time the user moved their mouse wheel 1 millimeter, a Javascript callback would fire off, block the main UI thread, forcefully query the DOM for getBoundingClientRect(), and then force a heavy reflow by altering margin-top or top properties. This was awful for performance, causing extreme "scroll jank."
The Framer Motion Solution
Framer Motion solves performance issues through two massive architectural advantages:
- Native Browser APIs:
For scroll-triggered elements (
whileInView), Framer Motion uses a highly optimized, pooledIntersectionObserver. It does not calculate exact scroll coordinates recursively; it simply lets the browser's C++ engine figure out when a bounding box overlaps with the viewport, which costs zero Javascript execution overhead. - ScrollTimeline & CSS Hardware Acceleration:
For scroll-linked animations (
useScroll), Framer Motion pushes changes strictly to hardware-accelerated CSS properties (liketransform: translate3dorscaleoropacity). The browser passes this workload to the GPU, entirely skipping the layout rasterization and painting steps on the CPU. Furthermore, modern Framer Motion actively detects if the browser supports theScrollTimelineAPI. If it does, Framer Motion rips the animation out of React's render cycle completely and delegates it straight to the browser's compositor.
In short, assuming you animate opacity, x, y, scale, or rotate, your animations will hit perfect 60fps or 120fps metrics with practically zero performance tax.
Comparing Framer Motion With Alternatives
Is Framer Motion the only way to do this? No, but it's arguable the best for React environments. Let's compare perfectly equivalent competitors.
| Feature | Framer Motion | GSAP | React Spring |
|---|---|---|---|
| React-First API | Framework-agnostic (works well with @gsap/react) | ||
| Scroll Animations | Good (useScroll API) | Best / Industry standard (ScrollTrigger) | Limited |
| Ease of Use | Very High | Medium | Medium–Low |
| Complex Sequencing | Good | Industry Standard | Good |
| Performance | High (uses WAAPI/GPU) | Excellent | High |
| Bundle Size | ~30-40kb (modern split) | ~40kb+ (with plugins) | ~15kb |
| Timeline Control | Basic | Unmatched | Basic |
| SVG Animations | Good | Best | Good |
| Physics Animations | Built-in (Springs) | Requires plugin/custom | Core feature |
Framer Motion vs. GSAP
GSAP (GreenSock Animation Platform) is incredibly powerful and considered the gold standard in the broader web industry for sequencing and raw timeline physics. GSAP's ScrollTrigger plugin is legendary. However, GSAP is DOM-first, not React-first. Interfacing GSAP with a React lifecycles (strict mode, unmounting, hot reloading) requires extensive usage of useLayoutEffect, cleanup functions, and imperative boilerplate logic and it has useGSAP() hook which reduces the complexity of interating it with React. Framer Motion, by contrast, is purely declarative React.
Framer Motion vs. React Spring
React Spring focuses heavily on simulating literal physics (mass, tension, friction) rather than pure easing curves and duration. While React Spring is fantastic for highly technical micro-interactions, building complex scroll-linked timelines requires significantly more mental overhead compared to Framer Motion's clean useTransform mappings.
Framer Motion vs. React Animate On Scroll / React Reveal
Older libraries like react-animate-on-scroll typically inject static CSS classes when an element is detected. They are usually highly limited to simple fade-ins and bounce-ins. They fundamentally cannot handle synchronous, interpolatable scroll-linked animations like parallax or clip-path reveals. They are largely obsolete in the modern era of Framer Motion.
The Ultimate Hack: Drive Conversions Faster with ogblocks
Let's pivot for a second. We've shown you how to build a world-class framer motion scroll animation from scratch. You've seen the code, the hooks, and the mathematics.
But configuring useScroll, dialing in your spring coefficients, managing SVG paths, and ensuring mobile responsiveness takes hours—sometimes days—for complex layouts. If you are a SaaS owner or a freelance developer on a tight deadline, your time is your most valuable asset.
You shouldn't be reinventing the wheel trying to write boilerplate clipPath interpolation logic. Your main goal is to ship a beautiful landing page that converts visitors into paying customers.
That's where ogblocks comes in.
ogblocks is a premium library of expertly crafted, insanely beautiful React components built specifically with Framer Motion and Tailwind CSS. We have painstakingly designed, coded, and performance-optimized hundreds of text effects, scroll reveals, animated pricing cards, and interactive bento grids.
Instead of writing 300 lines of complex scroll hooks, you simply copy and paste an ogblocks component directly into your Next.js project. You get the pixel-perfect design, the hardware-accelerated scroll animations, and the accessibility out-of-the-box, making it the best framer component library available.
Stop wasting days trying to perfect a scroll marquee. Check out ogblocks today and elevate your application's UI to world-class standards in minutes.
Conclusion
Understanding how to execute a proper react scroll animation in Framer Motion completely changes the way you approach web development. It shifts your mindset from building static document pages to architecting fluid, interactive user experiences.
By mastering scroll-triggered methods using whileInView, you ensure your content reveals itself with grace and intent. By unlocking scroll-linked properties using useScroll and useTransform, you build multi-layered parralax effects and dynamic visual progress trackers that keep users engaged and scrolling all the way down to your call-to-action.
Embrace Framer Motion, stick to hardware-accelerated transforms (y, opacity, scale), and if you ever need to skip the boilerplate, grab pre-built masterpieces from the ogblocks ecosystem. Happy animating!
FAQ
What is a react scroll animation in Framer Motion?
A react scroll animation in Framer Motion is an animation that dynamically responds to user scrolling. It comes in two forms: scroll-triggered (where elements animate as they enter the screen using whileInView), and scroll-linked (where physical properties like size and position are strictly mapped to the scroll progress percentage using the useScroll hook).
Is it hard to implement a parallax scroll effect in React?
No! With Framer Motion, implementing a parallax framer motion scroll animation is simply a matter of tracking the scrollY value and mapping it to a y transformation vector using the useTransform hook. By making the background animate slower than the foreground element, the illusion of 3D parallax depth is achieved seamlessly.
How do I stop a scroll animation from repeating every time I scroll up and down?
You can control whether an animation repeats or only triggers exactly once by passing the viewport prop directly to your motion element. specifically, use <motion.div viewport={{ once: true }} /> to restrict the animation to a single, one-off execution when it first enters the browser viewport.
Do scroll animations slow down React applications?
When built poorly using traditional window.addEventListener('scroll') methods, yes, they cause massive scroll-jank. However, Framer Motion bypasses this entirely using highly optimized ResizeObservers and the ScrollTimeline API, pushing rendering tasks away from the CPU thread completely over to the GPU via hardware-accelerated CSS transforms. Ensure you animate safe properties like scale, rotate, and opacity for perfect 60-120fps performance.
Written by Karan
ogBlocks is an Animated React UI Component library built with Motion and Tailwind CSS