All guidesAnimation

framer-motion animations for beginners

7 min read

framer-motion takes the tedious manual work out of animation. Instead of managing keyframes and timing yourself, you only describe the target state and the library computes the path there. This guide takes you from your first motion to staggered lists and shows what matters for calm, high-quality motion.

The motion element as the base

Every animation starts with a motion element. A div becomes motion.div, a button becomes motion.button. These elements behave like their normal counterparts but understand extra props for motion.

With the animate prop you define how the element should look. A value like animate with opacity 1 and y 0 describes the target state. When this value changes, framer-motion animates there smoothly without you calculating the path in between.

For the start state you use initial. This way an element fades in from opacity 0 and a slight shift on load. That produces the typical calm slide-up that shapes the first impression on many pages.

Control transitions with transition

The transition prop determines the pace and character of the motion. With duration you set the time in seconds, with ease the acceleration curve. Values between 0.3 and 0.6 seconds feel pleasant for most UI motions.

Instead of a curve you can also pick a spring. With type spring the motion responds to stiffness and damping and feels more physical. For calm interfaces a soft curve like [0.22, 1, 0.36, 1] often stays the better choice, because it eases out more controlled.

Variants for clean states

As soon as an element has several states, inline values get messy. Variants solve this: you define named states like hidden and visible as an object and reference them through initial and animate by their name only.

The big advantage shows with nested elements. A parent can pass its variants down to all children. That way you control a whole group with a single state change, without addressing each child individually.

Stagger lists with staggerChildren

When many elements appear at once, it feels flat. With staggerChildren in the parent variant you set a small offset between the children, usually 0.05 to 0.12 seconds. The elements then appear one after another and the eye is guided.

For this to work, each child gets the same variant names as the parent. framer-motion handles the order and the spacing. For cards, navigation items or feature lists this is an effective, subtle effect.

Animate on scroll

Many motions should only trigger once an element enters the visible area. For that you replace animate with whileInView and use viewport to define when and how often the animation starts. With once true it runs only the first time it becomes visible.

This avoids content further down having played its fade-in before the user even sees it. The result is a page that builds up calmly and lively as you scroll.

Keep motion accessible

Not everyone wants to see motion. The hook useReducedMotion from framer-motion reads the system setting prefers-reduced-motion. When it is active you deliver a calmer variant, for example just a fade-in without any shift.

Also keep animations short and avoid strong scaling, rotations or hectic jumping. Good motion supports the content and never pushes itself into the foreground.