Back to Blog
3 Methods for Infinite Animation in Framer Motion (2026) – cover image comparing React animation libraries

3 Methods for Infinite Animation in Framer Motion (2026)

·
Karan

Framer Motion Infinite Animation: The Ultimate Guide for React Developers

Key Takeaways

  • Infinite loops are created by explicitly setting the transition object's repeat property to Infinity.

  • Avoid jagged resets by always using linear easings for continuous rotations and marquees (ease: "linear").

  • Wildcard keyframes using null values allow you to hold transform states during complex choreographed loops.

  • Never ship endless motion without respecting user accessibility via Framer Motion's useReducedMotion hook.

Table of Contents

Animations are the lifeblood of modern, engaging web applications. While subtle entrance and exit transitions provide a baseline of polish, Framer motion infinite animation takes your React application's user experience to an entirely new level. Infinite animations—whether they are endlessly scrolling client marquees, gently floating background elements, or continuously spinning loading states—communicate activity, establish visual rhythm, and inject personality into otherwise static interfaces.

In this comprehensive guide, we will dive deep into everything you need to know to create highly performant, accessible, and visually stunning infinite animations using Framer Motion (now formally known as Motion) in your React projects. Whether you are an indie hacker launching a new SaaS, a frontend developer at an enterprise company, or a designer looking to level up your code skills, this article will equip you with the practical knowledge and code patterns necessary to ship production-ready motion. If you are learning how to integrate these animations directly into a meta framework like Next.js, we also highly recommend reading our Ultimate Guide to Framer Motion and Next.js first.

We will explore multiple techniques, ranging from the fundamental transition prop to advanced null wildcard keyframes, and even take a look at the newly introduced Motion+ <Ticker /> component for flawless infinite marquees. Let's get started.

The Performance Cost of CSS vs. Framer Motion

One of the most persistent questions among developers is: "Why should I use Framer Motion for infinite animations when I could just use CSS @keyframes?" It is a valid question. CSS animations are native to the browser, generally performant for simple transforms, and require no additional JavaScript payload.

However, as animations grow in complexity, hand-rolling CSS soon becomes a maintenance nightmare. Managing complex timing functions, orchestrating multiple animated elements, and synchronizing state changes with CSS alone is notoriously difficult. Moreover, when building dynamic React applications, you often need your animations to react to component state, props, or user interactions—capabilities that static CSS struggles to provide gracefully.

This is where Framer Motion excels. Under the hood, Framer Motion doesn't just arbitrarily animate values. It uses an optimized rendering loop that bypasses the React render cycle whenever possible. When you animate hardware-accelerated properties—specifically transform (like translate, scale, rotate) and opacity—Framer Motion ensures these animations are handed off effectively to the browser's compositor thread via the Web Animations API (WAAPI) in modern browsers, or highly optimized requestAnimationFrame loops as fallbacks.

This means you get the best of both worlds: the declarative, state-driven, and highly readable API of React and Framer Motion, coupled with performance that rivals or beats hand-written CSS. Instead of worrying about triggering expensive browser layout recalculations (jank), you can focus on the creative aspects of your infinite loops.

Method 1: Using the transition Prop for Infinite Loops

The most common and fundamental way to create a Framer motion infinite animation is by leveraging the transition prop. In Framer Motion, the transition object governs how values animate from one state to another. By configuring specific properties within this object, we can instruct the animation to repeat endlessly.

The core property responsible for this is repeat. Setting it to a specific number instructs Motion to repeat the animation that many times. However, to achieve an infinite loop, we utilize the JavaScript global property Infinity.

Basic Spinning Animation Example

Let's look at the classic spinning loader or rotating logo. This is the simplest demonstration of a continuous loop.

import { motion } from "motion/react";
export const SpinningLogo = () => {
return (
<div className="flex items-center justify-center p-10 bg-slate-900 rounded-xl">
<motion.div
className="w-16 h-16 bg-blue-500 rounded-lg shadow-lg"
animate={{ rotate: 360 }}
transition={{
repeat: Infinity,
ease: "linear",
duration: 2,
}}
/>
</div>
);
};

In this example, we tell the motion.div to animate its rotate property to 360 degrees. The magic happens in the transition object:

  1. repeat: Infinity ensures the animation never stops.
  2. ease: "linear" is absolutely crucial here. Most default easings (like easeOut) slow down near the end. If a spinning animation slows down before repeating, it will look jagged and unnatural. A linear easing ensures a constant velocity throughout the entire 360-degree rotation, making the loop seamless.
  3. duration: 2 dictates that each full rotation takes precisely 2 seconds.

Understanding repeatType: Loop, Reverse, and Mirror

While spinning is great, what if you want an element to float up and down, or pulse in and out? By default, when a repeating animation finishes, it immediately jumps back to its starting value and starts again. This jump is perfect for a 360-degree rotation (because 0 degrees looks identical to 360 degrees), but it looks terrible for positional movements.

This is where repeatType comes into play. It dictates how the animation repeats, offering three distinctive modes:

  1. loop (Default): The animation repeats from the start instantly. Perfect for rotation and seamless scrolling.
  2. reverse: The animation alternates between playing forwards and backwards. This is ideal for floating, pulsing, or pendulum-like movements.
  3. mirror: Similar to reverse, but it switches the animation origin and target on each iteration.

Here is an example of a floating element using repeatType: "reverse":

import { motion } from "motion/react";
export const FloatingElement = () => {
return (
<div className="flex items-center justify-center p-20 bg-slate-900 rounded-xl overflow-hidden relative">
{/* Background glow just for aesthetic flair */}
<div className="absolute w-32 h-32 bg-purple-500/20 blur-3xl rounded-full" />
<motion.div
className="w-24 h-24 bg-gradient-to-tr from-purple-500 to-blue-500 rounded-2xl shadow-2xl relative z-10 box-border border border-white/10"
animate={{
y: ["-15px", "15px"]
}}
transition={{
repeat: Infinity,
repeatType: "reverse",
ease: "easeInOut",
duration: 2,
}}
/>
</div>
);
};

Notice a few key differences here compared to our spinning example:

  • We are using an array for the y transform: ["-15px", "15px"]. This defines explicit keyframes (start at -15px, end at +15px).
  • repeatType: "reverse" ensures that once the element reaches 15px, the next iteration smoothly animates it back up to -15px.
  • We use an easeInOut function (which provides physics-like acceleration and deceleration) to make the floating motion feel entirely natural, as if the element is gently bobbing on water.

Method 2: Creating Infinite Scrolling Marquees with Framer Motion

One of the most requested features in frontend development is the infinite scrolling marquee. Countless hours have been lost writing convoluted CSS or complex React state logic to clone DOM elements to achieve a seamless, jumping-free scroll.

While premium solutions like Motion+ offer dedicated components for this, we can build a highly performant and accessible infinite scrolling marquee using pure React and Framer Motion. The trick is to duplicate our list of items so that the animation can loop seamlessly without any empty space appearing.

Here is the code for a ClientMarquee component that smoothly scrolls a list of clients:

"use client";
import { motion } from "motion/react";
export const ClientMarquee = () => {
const clients = [
"Acme Corp", "GlobalTech", "Stark Industries", "Wayne Enterprises",
"Cyberdyne", "Initech", "Soylent Corp", "Massive Dynamic"
];
// We duplicate the array to allow for a seamless infinite scroll loop
const duplicateClients = [...clients, ...clients];
return (
<div className="w-full bg-neutral-900 py-12 overflow-hidden border-y border-white/10 flex my-6 relative">
<div className="absolute inset-y-0 left-0 w-24 bg-gradient-to-r from-neutral-900 to-transparent z-10" />
<div className="absolute inset-y-0 right-0 w-24 bg-gradient-to-l from-neutral-900 to-transparent z-10" />
<motion.div
className="flex min-w-max"
animate={{ x: ["0%", "-50%"] }}
transition={{
ease: "linear",
duration: 20,
repeat: Infinity,
}}
>
{duplicateClients.map((client, idx) => (
<div
key={idx}
className="text-2xl md:text-3xl font-bold text-slate-500 px-8 whitespace-nowrap"
>
{client}
</div>
))}
</motion.div>
</div>
);
};
Acme Corp
GlobalTech
Stark Industries
Wayne Enterprises
Cyberdyne
Initech
Soylent Corp
Massive Dynamic
Acme Corp
GlobalTech
Stark Industries
Wayne Enterprises
Cyberdyne
Initech
Soylent Corp
Massive Dynamic

The Infinite Loop Trick

Let's break down how this works:

  1. Duplicating the Content: By rendering [...clients, ...clients], we ensure that as the first set of clients scrolls out of view to the left, the identical second set follows directly behind it.
  2. The Magic Animation: The animate={{ x: ["0%", "-50%"] }} is the core of the illusion. We animate the entire duplicated container from 0% to exactly -50% of its width.
  3. The Seamless Reset: Because the container is perfectly duplicated, the moment it hits -50% (which visually looks identical to 0%), the repeat: Infinity transition instantly snaps it back to 0%. This cut is completely invisible to the user, creating the illusion of a never-ending scroll!
  4. Gradients for Polish: The absolute positioned z-10 divs apply a sleek fade-out effect on the edges of the marquee, making the entrance and exit of elements look incredibly premium.

Method 3: Advanced Infinite Keyframes

For more complex, choreographed sequences that repeat infinitely, simply floating up and down is not enough. You might need a character sprite to cycle through an animation, a loader to traverse multiple points in a complex path, or an element that pauses mid-animation before looping.

Framer Motion handles this via keyframe arrays and timing controls.

When you pass an array of values to an animate property (like we did briefly with y: ["-15px", "15px"]), Framer Motion treats these as keyframes. By default, it spaces them out evenly over the given duration.

However, using the times array inside the transition object, you can precisely dictate when each keyframe occurs. The times array takes numbers from 0 to 1 (representing 0% to 100% of the duration).

Let's look at a complex pulsing loader that uses wildcard keyframes (using null). A null keyframe tells Framer Motion to "hold" the previous value. Let's create an animation that scales up, holds the large scale for a moment, and then scales down quickly.

import { motion } from "motion/react";
export const ComplexPulseLoader = () => {
return (
<div className="flex items-center justify-center p-20 bg-slate-900 rounded-xl relative">
<motion.div
className="w-16 h-16 bg-emerald-500 rounded-full shadow-[0_0_30px_rgba(16,185,129,0.5)]"
animate={{
// Keyframes: Start at 1 -> Grow to 1.5 -> Hold at 1.5 -> Shrink to 1
scale: [1, 1.5, null, 1],
// Simultaneously animate opacity
opacity: [0.5, 1, 1, 0.5]
}}
transition={{
duration: 3,
repeat: Infinity,
// 0% -> 20% -> 80% -> 100%
times: [0, 0.2, 0.8, 1],
ease: ["easeInOut", "linear", "easeInOut"]
}}
/>
</div>
);
};

In this advanced setup:

  • The scale array goes from 1 to 1.5, then hits null. This null wildcard keyframe means "stay at 1.5". It prevents you from having to statically hardcode 1.5 twice, which improves maintainability.
  • The times: [0, 0.2, 0.8, 1] array perfectly synchronizes with the 4 items in our scale/opacity keyframe arrays.
    • At 0 (0s), scale is 1.
    • By 0.2 (0.6s), it rapidly grows to 1.5.
    • Between 0.2 and 0.8 (0.6s to 2.4s), it holds the 1.5 scale—creating a long pause at the apex of the pulse.
    • Finally, from 0.8 to 1 (2.4s to 3.0s), it shrinks back to 1.
  • repeat: Infinity loops this choreographed sequence endlessly.

Best Practices for Accessible React Animations

We absolutely cannot write a comprehensive guide on Framer motion infinite animation without discussing web accessibility (a11y).

Infinite motion, while visually appealing, can be highly problematic for users with vestibular disorders. Continuous, unpredictable, or large-scale motion can trigger dizziness, vertigo, and nausea.

Modern operating systems allow users to explicitly specify that they prefer reduced motion via accessibility settings. As responsible developers, we must respect this system-level preference.

Framer Motion makes this incredibly straightforward via the useReducedMotion hook.

import { motion, useReducedMotion } from "motion/react";
export const AccessibleInfiniteMarquee = () => {
// Returns true if the user has requested reduced motion in their OS
const prefersReducedMotion = useReducedMotion();
return (
<div className="overflow-hidden">
<motion.div
className="flex gap-4 font-bold text-4xl"
// If reduced motion is preferred, don't animate the x value at all.
animate={{
x: prefersReducedMotion ? 0 : ["0%", "-100%"]
}}
transition={{
repeat: Infinity,
ease: "linear",
duration: 10
}}
>
<span>Endless scrolling accessibility respecting text</span>
{/* Duplicated content for seamless loop */}
</motion.div>
</div>
);
};
Endless scrolling accessibility respecting text • Endless scrolling accessibility respecting text • Endless scrolling accessibility respecting text • Endless scrolling accessibility respecting text •

By integrating useReducedMotion, you are ensuring that your beautiful infinite animations augment the experience for users who desire them, while safely disabling the motion for users who require a static interface. Be aware that the new <Ticker /> component from Motion+ actually handles reduced motion automatically out-of-the-box, saving you from writing this boilerplate yourself!

(Note: For animations that trigger sequentially as you scroll down the page instead of looping infinitely, read our complete tutorial on React scroll animations.)

FAQ: Framer Motion Infinite Animations

How do I stop an infinite animation in Framer Motion?

To stop an infinite animation, you need to tie the animate prop to a piece of React state or utilize useAnimation controls. When the stopping condition is met, update the state object passed to animate to remove the repeating transition, or call controls.stop().

Why is my Framer Motion loop stuttering when it repeats?

A stuttering or jagged loop usually happens because the easing function is slowing down at the end of the transition before jumping back to the start. For continuous movements like 360-degree rotations or scrolling marquees, you must explicitly set the easing to ease: "linear" so the velocity remains perfectly constant.

Is CSS better for infinite animations than Framer Motion?

For extremely simple, standalone keyframes (like a basic spinning SVG), CSS is perfectly adequate. However, for dynamic React applications where animations need to respond to state changes, synchronize with other components, or utilize complex orchestrations (like spring physics), Framer Motion is vastly superior and significantly easier to maintain while still offering highly optimized rendering.

Conclusion

Mastering Framer motion infinite animation grants you the power to create deeply engaging, premium-feeling user interfaces that captivate your audience without sacrificing performance. Whether you are building subtle background floats using repeatType: "reverse", choreographing complex paused rhythms with wildcard keyframes and times arrays, or leveraging the ultra-performant <Ticker /> for endless client marquees, the principles remain the same. Always remember to prioritize hardware-accelerated properties, rely on ease: "linear" for continuous non-reversing loops, and critically, respect useReducedMotion for accessibility.

Building beautiful UIs piece by piece can be time-consuming, even when you know all the Framer Motion secrets. If you want to skip the boilerplate and instantly drop fully animated, breathtaking React components directly into your Next.js SaaS apps or landing pages, check out ogBlocks. It is the ultimate collection of meticulously designed, production-ready React components that will instantly elevate your product's design language, saving you countless hours of fine-tuning animations. Start building ship-ready interfaces today with ogBlocks.

Written by Karan

ogBlocks is an Animated React UI Component library built with Motion and Tailwind CSS

3 Methods for Infinite Animation in Framer Motion (2026) | OGBlocks Blog | ogBlocks