Advanced Framer Motion

Advanced Framer Motion

Verified Sources
Jun 19, 2026

Framer Motion (now known as Motion for React) is the production-grade animation library for React that goes far beyond simple transitions. While most developers are familiar with its basic animate and transition props, advanced Framer Motion unlocks a powerful toolkit: layout animations, gesture-driven interactions, orchestration, and low-level MotionValues for fine-grained control.

This course section dives deep into the advanced APIs — useMotionValue, useTransform, useScroll, layoutId, AnimatePresence, and orchestration patterns — that separate amateur animations from polished, professional interfaces.

The core mental model: every animation in Framer Motion is driven by values. The declarative animate prop is syntactic sugar over the imperative MotionValue system underneath.

At the advanced level, you'll learn to combine all three branches of this architecture to build animation systems that are performant, composable, and delightful.

5 Advanced Framer Motion Techniques I Shouldn't Have Skipped

1. MotionValues — The Reactive Primitives

A MotionValue is the fundamental building block of every Framer Motion animation. When you write animate={{ x: 100 }}, Framer Motion creates a MotionValue internally to track x.

Why Use MotionValues Directly?

  • Avoid re-renders: MotionValues update outside React's render cycle, making them ideal for scroll-linked or drag-linked animations where 60fps updates would otherwise trigger 60 re-renders per second.
  • Compose and transform: Chain values together with useTransform to create derived values without React state.
  • Read imperatively: Access .get()/.set() for programmatic control.
ApproachRe-rendersBest For
animate propYes (state-driven)Simple mount/exit animations
variantsTriggered onlyMulti-property orchestrated sequences
MotionValuesNoScroll, drag, gesture, continuous tracking
useAnimateMinimalTimeline-driven imperative sequences

Creating and Using MotionValues

The useMotionValue(initial) hook initializes a value, and you bind it to a component via the style prop:

1import { motion, useMotionValue } from "framer-motion"; 2 3function DraggableBox() { 4 const x = useMotionValue(0); 5 const scale = useMotionValue(1); 6 7 return ( 8 <motion.div 9 drag="x" 10 style={{ x, scale }} 11 onDrag={() => scale.set(1.1)} 12 onDragEnd={() => scale.set(1)} 13 /> 14 ); 15}

The drag prop automatically updates the x MotionValue, and since scale is also a MotionValue, the scale transition happens without any re-render.

Performance: MotionValues vs State

Always prefer useMotionValue over useState for values that change every frame (scroll position, drag coordinates, pointer tracking). A useState update triggers a full React re-render on every frame — a MotionValue update just changes a style property directly through the animation engine, bypassing React entirely.

2. Value Transformation with useTransform

useTransform creates a derived MotionValue — it maps the output of one MotionValue through a transformation function or a range mapping. This is the compositional superpower of Framer Motion.

Range Mapping Syntax

The most common pattern is mapping input ranges to output ranges:

youtput=transform(xinput)y_{\text{output}} = \text{transform}(x_{\text{input}})

Where the mapping is defined by corresponding input/output range pairs:

output=f(input),f is a piecewise linear interpolation\text{output} = f(\text{input}), \quad f \text{ is a piecewise linear interpolation}

1import { useScroll, useTransform, motion } from "framer-motion"; 2 3function ParallaxSection() { 4 const { scrollYProgress } = useScroll(); 5 const y = useTransform(scrollYProgress, [0, 1], [0, -200]); 6 const opacity = useTransform(scrollYProgress, [0, 0.5], [1, 0]); 7 8 return ( 9 <motion.div style={{ y, opacity }}> 10 This content parallax-scrolls and fades. 11 </motion.div> 12 ); 13}
ParamTypeDescription
valueMotionValueThe source value to transform
inputRangenumber[]Monotonically increasing input values
outputRangenumber[] | string[]Corresponding output values (supports colors, px, deg)
options.clampbooleanWhether to clamp output beyond range (default: true)

Function Transformer

You can also pass a function for non-linear mappings:

1const rotate = useTransform(x, (latestX) => latestX * 0.5); 2const color = useTransform( 3 dragDistance, 4 (d) => (d > 100 ? "#ff4444" : "#44aaff") 5);

Chaining Transforms

Since useTransform returns a MotionValue, you can chain them:

Building a Scroll-Linked Parallax Animation

  1. 1
    Step 1

    Use useScroll() to obtain a scrollYProgress MotionValue. Optionally pass a target ref and offset array to track a specific element entering/exiting the viewport.

    1const { scrollYProgress } = useScroll({ 2 target: sectionRef, 3 offset: ['start end', 'end start'] 4});
  2. 2
    Step 2

    Create as many derived MotionValues as needed using useTransform. Each maps a different range of the scroll progress to a specific animation property.

    1const y = useTransform(scrollYProgress, [0, 1], [100, -100]); 2const scale = useTransform(scrollYProgress, [0, 0.5, 1], [0.8, 1, 0.8]); 3const rotate = useTransform(scrollYProgress, [0, 1], [0, 360]);
  3. 3
    Step 3

    Pass the derived MotionValues to motion.* elements via the style prop. MotionValues bypass React's render cycle, so these update at 60fps without re-renders.

    1<motion.div style={{ y, scale, rotate }}> 2 Parallax Content 3</motion.div>
  4. 4
    Step 4

    For scroll-smoothing effects, wrap raw MotionValues with useSpring to add physics-based interpolation. This prevents janky linear scroll mapping.

    1import { useSpring } from 'framer-motion'; 2const smoothY = useSpring(y, { stiffness: 100, damping: 30 });
  5. 5
    Step 5

    Create depth by applying different parallax rates to different layers. Backgrounds move slower (smaller range), foregrounds move faster (larger range). This creates a convincing parallax effect.

    1const bgY = useTransform(scrollYProgress, [0,1], [0, -50]); 2const fgY = useTransform(scrollYProgress, [0,1], [0, -200]);

3. Advanced Orchestration with Variants

Variants allow you to define named animation states and propagate them through the motion component tree. This is the primary tool for orchestrating complex, multi-element sequences.

The Inheritance Model

When a parent changes its animate prop, all descendant motion components receive the same variant label. This means you only need to toggle the parent to orchestrate the entire tree.

Staggered Children with staggerChildren

The staggerChildren transition option delays each child's animation relative to its predecessor:

1const container = { 2 hidden: { opacity: 0 }, 3 visible: { 4 opacity: 1, 5 transition: { 6 staggerChildren: 0.08, 7 delayChildren: 0.2, 8 }, 9 }, 10}; 11 12const item = { 13 hidden: { y: 20, opacity: 0 }, 14 visible: { y: 0, opacity: 1 }, 15}; 16 17function StaggeredList({ items }) { 18 return ( 19 <motion.ul 20 variants={container} 21 initial="hidden" 22 animate="visible" 23 > 24 {items.map((text, i) => ( 25 <motion.li key={i} variants={item}> 26 {text} 27 </motion.li> 28 ))} 29 </motion.ul> 30 ); 31}

Dynamic Variants

Variants can be functions that receive custom data, allowing per-item customization:

1const item = { 2 hidden: (custom) => ({ 3 opacity: 0, 4 y: custom * 100, 5 }), 6 visible: (custom) => ({ 7 opacity: 1, 8 y: 0, 9 transition: { delay: custom * 0.1 }, 10 }), 11}; 12 13// Usage: pass custom prop to each child 14<motion.li custom={index} variants={item} />

Variant Propagation Gotcha

Non-motion components break the propagation chain. If you have a <div> between a parent motion.ul and child motion.li, the variant signal will NOT reach the children. Always use motion.* components for every element in the tree that needs to participate in the orchestration.

4. Layout Animations & Shared Layout Transitions

Layout animations are one of Framer Motion's most powerful features. They automatically animate an element from its old position/size to its new one when the DOM layout changes, using a technique inspired by FLIP.

The layout Prop

Simply add layout to any motion.* component. When React re-renders and the element's position or size changes, it animates smoothly:

1function ToggleGrid() { 2 const [isExpanded, setIsExpanded] = useState(false); 3 4 return ( 5 <motion.div 6 layout 7 style={{ 8 width: isExpanded ? "100%" : "50%", 9 }} 10 onClick={() => setIsExpanded(!isExpanded)} 11 /> 12 ); 13}

Shared Layout with layoutId

When two motion components share the same layoutId in different parts of the tree, Framer Motion automatically animates between them — even across route changes with AnimatePresence:

1function CardToModal() { 2 const [selected, setSelected] = useState(null); 3 4 return ( 5 <> 6 {items.map((item) => ( 7 <motion.div 8 layoutId={`card-${item.id}`} 9 onClick={() => setSelected(item)} 10 > 11 <motion.img layoutId={`image-${item.id}`} src={item.src} /> 12 <p>{item.title}</p> 13 </motion.div> 14 ))} 15 16 <AnimatePresence> 17 {selected && ( 18 <motion.div layoutId={`card-${selected.id}`}> 19 <motion.img layoutId={`image-${selected.id}`} /> 20 <p>{selected.body}</p> 21 </motion.div> 22 )} 23 </AnimatePresence> 24 </> 25 ); 26}

layoutDependency and layoutScope

Controlling when layout animations trigger is critical for performance:

  • layoutDependency: An array of values — layout animations only run when these values change
  • layoutScope: Groups elements that share layout animations together
  • layout="position": Only animate position, not size
  • layout="size": Only animate size, not position
1import { motion, useMotionValue, useTransform } from "framer-motion"; 2 3function DragTiltCard() { 4 const x = useMotionValue(0); 5 const y = useMotionValue(0); 6 7 // Map drag distance to rotation 8 const rotateX = useTransform(y, [-100, 100], [15, -15]); 9 const rotateY = useTransform(x, [-100, 100], [-15, 15]); 10 11 // Chain: rotate → brightness 12 const brightness = useTransform( 13 rotateY, 14 [-15, 0, 15], 15 [0.7, 1, 0.7] 16 ); 17 18 return ( 19 <motion.div 20 drag 21 dragElastic={0.18} 22 style={{ 23 x, y, rotateX, rotateY, 24 filter: useTransform(brightness, (b) => `brightness(${b})`), 25 }} 26 whileTap={{ scale: 1.05 }} 27 > 28 Drag me! 29 </motion.div> 30 ); 31}

5. Exit Animations with AnimatePresence

AnimatePresence solves a fundamental React problem: when a component unmounts, it disappears instantly. AnimatePresence keeps elements in the tree long enough to animate them out.

Key Props

PropTypeDescription
mode"sync" | "wait" | "popLayout"How entering/exiting components interact
onExitComplete() => voidCallback when all children have finished exiting
customanyCustom data passed to variants for directional exits

The mode Prop — Critical for UX

  • sync (default): New element enters while old exits — can cause overlap
  • wait: Old exits completely, then new enters — no overlap but feels slower
  • popLayout: Exiting elements collapse to position: absolute and animate out, while remaining siblings immediately re-layout — best for list mutations

Directional Exits with custom

Pass custom data to make exits animate in the logical direction:

1function PageTransition({ direction, children }) { 2 return ( 3 <AnimatePresence custom={direction} mode="wait"> 4 <motion.div 5 key={direction} 6 custom={direction} 7 variants={{ 8 enter: (dir) => ({ x: dir > 0 ? 300 : -300, opacity: 0 }), 9 center: { x: 0, opacity: 1 }, 10 exit: (dir) => ({ x: dir > 0 ? -300 : 300, opacity: 0 }), 11 }} 12 initial="enter" 13 animate="center" 14 exit="exit" 15 > 16 {children} 17 </motion.div> 18 </AnimatePresence> 19 ); 20}

6. The useAnimate Hook — Imperative Timeline Control

The useAnimate hook provides programmatic, timeline-like animation control. It returns a scope ref and a animate function, letting you define sequenced animations imperatively:

1import { useAnimate } from "framer-motion"; 2 3function AnimatedButton() { 4 const [scope, animate] = useAnimate(); 5 6 const handleClick = async () => { 7 await animate(scope.current, { scale: 0.95 }, { duration: 0.1 }); 8 await animate(scope.current, { scale: 1 }, { type: "spring" }); 9 await animate(".icon", { rotate: 360 }, { duration: 0.4 }); 10 }; 11 12 return ( 13 <motion.button ref={scope} onClick={handleClick}> 14 <span className="icon">🔄</span> Click Me 15 </motion.button> 16 ); 17}

The animate() function is awaitable — it returns a Promise that resolves when the animation completes. By chaining await calls, you create a sequential animation timeline without nested callbacks.

Animating Children

The animate function can target CSS selectors within the scope:

1// Animates all elements matching .particle inside scope 2await animate(".particle", { opacity: 0, y: -50 }, { delay: stagger(0.05) }); 3 4// You can also animate specific MotionValues 5await animate(x, 100, { type: "spring" });

Framer Motion API Comparison

When to use each advanced API based on use-case requirements

7. Gesture-Driven Animations

Framer Motion's gesture system ties directly into MotionValues for high-performance interactive animations.

Drag with Constraints and Physics

1<motion.div 2 drag 3 dragConstraints={{ left: -200, right: 200, top: -100, bottom: 100 }} 4 dragElastic={0.1} 5 dragTransition={{ bounceStiffness: 300, bounceDamping: 20 }} 6 whileDrag={{ scale: 1.05, boxShadow: "0 10px 30px rgba(0,0,0,0.3)" }} 7/>
PropTypeDescription
dragboolean | "x" | "y"Enable drag on specific or all axes
dragConstraintsRefObject | {top, right, bottom, left}Bounding box or ref to container
dragElasticnumber | {top, right, bottom, left}How far beyond constraints (0 = rigid, 1 = very elastic)
dragMomentumbooleanWhether element keeps sliding after release
dragSnapToOriginbooleanAlways spring back to initial position
onDragStart/onDrag/onDragEndfunctionLifecycle callbacks receiving drag info

Gesture Shortcuts

1<motion.button 2 whileHover={{ scale: 1.05, backgroundColor: "#6366f1" }} 3 whileTap={{ scale: 0.95, backgroundColor: "#4f46e5" }} 4 whileFocus={{ outline: "2px solid #6366f1" }} 5 whileInView={{ opacity: 1, y: 0 }} 6 viewport={{ once: true, margin: "-100px" }} 7/>

The [whileInView](def="A gesture-trigger prop that animates an element when it enters the viewport, with optional one-time and margin settings") prop is particularly powerful for scroll-triggered animations and pairs with the viewport option to control intersection observer thresholds.

Advanced Framer Motion Learning Path

MotionValue Fundamentals

Phase 1

Master useMotionValue, .get()/.set(), and binding to the style prop. Build a drag tracker that logs positions without re-renders."

Transformations & Scrolling

Phase 2

Learn useTransform range mapping, useScroll with target/offset, and useSpring for smoothed scroll-linked animations."

Variant Orchestration

Phase 3

Build staggered lists, dynamic variant functions with custom, and deeply nested propagated animations."

Layout & Shared Transitions

Phase 4

Implement layout prop animations, layoutId for cross-component shared transitions, and FLIP-based multi-element morphing."

AnimatePresence & Exits

Phase 5

Handle exit animations, directional exits with custom, mode prop options ('sync', 'wait', 'popLayout'), and list mutations."

Imperative Timelines

Phase 6

Use useAnimate for awaitable animation sequences, CSS selector targeting, and complex choreographed timelines."

Advanced Topics & Edge Cases

Advanced Framer Motion Key Concepts

1 / 6
17%
Question · Term

What is a MotionValue?

Click to reveal
Answer · Definition

A reactive value container that tracks a single animated value outside React's render cycle. Updated at 60fps without triggering re-renders. Created with useMotionValue(initial) and bound via style prop.

Knowledge Check

Question 1 of 5
Q1Single choice

Which hook creates a reactive value that updates outside React's render cycle?

Explore Related Topics

1

Startup Fundamentals

The course outlines core concepts and stages to build, fund, and scale a startup.

  • Define the problem, craft a value proposition, and validate with an MVP.
  • Confirm product‑market fit using the 40%40\% “disappointed customer” rule and Retention>80%\text{Retention} > 80\%.
  • Monitor burn rate, maintain a 12‑18 month runway, and control cash flow.
  • Use a cap table to track equity, prevent over‑dilution, and prepare transparent pitch decks.
2

Retrieval-Augmented Generation (RAG) — From Fundamentals to Production-Ready Agentic RAG Systems

Retrieval‑Augmented Generation (RAG) couples external evidence retrieval with LLM generation to deliver up‑to‑date, grounded answers while mitigating hallucinations.

  • Retrieval uses sparse (BM25), dense (vector embeddings) and hybrid methods; dense similarity is scored by cosine sim(q,di)=qdiqdi\text{sim}(q,d_i)=\frac{q\cdot d_i}{\|q\|\|d_i\|}.
  • Chunking strategy, metadata enrichment, and reranking are the highest‑leverage levers for retrieval quality and token efficiency.
  • Production pipelines separate offline ingestion (parsing, chunking, embedding, indexing) from online serving (query rewriting, hybrid retrieval, reranking, context assembly, constrained generation).
  • Agentic RAG extends standard RAG with planning, query decomposition, self‑critique, corrective retrieval loops, and tool use for multi‑hop or uncertain queries.
  • Robust deployments require multi‑level evaluation (recall, precision, faithfulness, citations), observability of each stage, and governance of latency, cost, and access control.
3

React Hooks in Depth

This course explains React Hooks, the functional alternative to class components, covering core hooks, usage rules, performance optimizations, and how to create custom hooks.

  • useState and useEffect replace class state and lifecycle methods; the dependency array controls when effects run.
  • Hooks must be called at the top level of React function components or custom hooks, and the ESLint plugin enforces these rules.
  • useMemo memoizes values and useCallback memoizes functions, both improving performance for expensive calculations or stable callbacks.
  • useReducer is preferred for complex state logic, following a reducer pattern similar to Redux.
  • Building a custom hook involves extracting reusable useState/useEffect logic into a function whose name starts with “use”.