Skip to content

5 Quick Framer Motion Tips

September 10, 2021

Introduction

Framer Motion is a library for React used to create animations for components in a simple declarative way.

Getting Started

npm i framer-motion

or

yarn add framer-motion

Creating an animation is as simple as it gets! All you have to do is import the motion component and use its "animate" property to change the value of an attribute or a style.

If the set value is different to the element's style or the value set in the "initial" prop framer motion will automatically create an animation.

In addition the motion component gives us access to the "transition" prop which lets us control the animation's duration, delay, type or whether we want the animation to loop.

<motion.div
animate={{ scale: 1.5 }}
transition={{ duration: 1, repeat: Infinity, repeatType: "reverse" }}
/>

1. Use Variants

Variants are objects that contain all the necessary information to create animations. They are passed to the "variants" prop of the motion component and are used to control the elements animation state.

Using variants we avoid writing inline code and we make our code more organized and easier to read.

If we alter the variant of a motion component that has children the change we made in the parent's animate property will affect all its children, making it easy to control whole groups of elements with just one state change.

const parentVariant = {
hidden: {
scale: 1
},
visible: {
opacity: 1,
scale: 2,
transition: {
duration: 0.5,
delayChildren: 0.5
}
}
}
const childVariant = {
hidden: {
scale: 0
},
visible: {
scale: 1
}
}
<motion.div
variants={parentVariant}
initial="hidden"
animate={isVisible ? "visible" : "hidden"}
onClick={() => {
setIsVisible((prev) => setIsVisible(!prev));
}}
>
<motion.div variants={childVariant} />
<motion.div variants={childVariant} />
<motion.div variants={childVariant} />
<motion.div variants={childVariant} />
</motion.div>

2. Create Dynamic Variants

Sometimes you want to create an animation that's only slightly different for each element. That's where dynamic variants come in handy.

We can accomplish that by making a function that returns a variant object and has as parameters the values we want to differentiate.

const childVariant = (scale) => ({
hidden: {
scale: 0
},
visible: {
scale: scale,
transition: {
repeat: Infinity,
duration: 2,
repeatDelay: 3
}
}
});
<motion.div initial="hidden" animate="visible">
<motion.div variants={childVariant(0.8)} />
<motion.div variants={childVariant(1)} />
<motion.div variants={childVariant(1.2)} />
<motion.div variants={childVariant(1.4)} />
</motion.div>

3. Targeted Transition Property

In more complex animations you don't always want all the attributes to animate for the same duration. For example, you might want an element's opacity animation to complete in 1 second, but its translateX animation to complete in 2 seconds.

All you have to do is pass an object inside the transition object that has as its key the name of the attribute you want to target.

<motion.div
initial={{ opacity: 0, x: -100}}
animate={{ opacity: 1, x: 0}}
transition={{
opacity: {
duration: 1
},
x: {
duration: 2
}
}}
/>

4. Animate SVGs

Animating SVGs is very similar to all other components. You turn the path element of the SVG into a motion component and use its attributes to create animations.

You can animate the SVG's fill, stroke, pathLength attributes and even the coordinates of the path itself inside the d attribute!

<svg width={300} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<motion.path
stroke="yellow"
d="M 1 10 h 30"
initial={{ pathLength: 0 }}
animate={{ pathLength: 1 }}
transition={{ duration: 3 }}
/>
</svg>

5. Layout Animations

Attributes that affect the components layout such as changes in position, flex and grid related attributes need a special property called layout to be animated correctly.

You have to set this property to true and change the component's style, through the style property or className, based on some state's value.

The component will then be automatically animated to its new position other components that have this prop and are affected by this change will also be automatically animated.

One use case that I've found particularly useful is animating a component from it's normal position to a fixed position on the screen, for example when the user scrolls down.

<motion.button
layout
style={
isFixed ? { position: "fixed", bottom: 20 } : { position: "relative" }
}
/>

I hope you found this post useful in some way and learned something new! As always the best way to learn is to write the code yourself and experiment with it.

Below are links to working examples of the things I covered in this post and the official documentation of Framer Motion: