Making cool animations with CSS is great but can be tricky when you want to create powerful ones. If you are not an expert in CSS this task can be more frustrating. With Framer motion, you don't need to be perfect in CSS, the hard work is already done for you. You just need to install the library, customize the values and create smooth animations.
What is Framer Motion
Framer Motion is an open-source React library to power production-ready animations. It will help you create fluid animations for the web across desktop and mobile. This makes creating complex animations easier, with its simple syntax. You can build gesture animation, variants, keyframes, drag, motion values, exit animations and more.
How to install Framer motion to your React project
- For you to start using it, you have to install the library through the node package manager first.
npm install framer-motion
- Import it to your project
import { motion } from "framer-motion"
- To use it in your React components you have to use:
Motion Components
Motion components are the heart of framer motion. By including the props (properties) you can add gestures and animations to your components. Without incorporating it you can't animate anything at all. You can easily initiate it by including motion.
before your div element.
- Motion components accept props like animate and transition for basic animations. The props can include single or multiple objects that will have keys and values to induct motion.
- let's start off by animating the title
import { motion } from "framer-motion"
<motion.h1
animate={
{fontSize: "3rem",
x: 20, y: -10
}
}>
Welcome to Framer Motion
</motion.h1>
Before I start to explain the results, let's first understand the meaning of the positive and negative values in x and y.
- To move to the right - Use a positive number
- To move to the left - Use a negative number
- To move upwards - Use a negative number
- To move downwards - Use a positive number
This means our h1
will first increase it's the font size by 3 rem, move to the right by 20px and then move up by 10px. The default value uses a px unit but if you want to use rems, you have to state it as I did with font size.
Using Initial prop
Apart from animate prop you can use the initial prop that illustrates how the component will look like before the animate property is indicated. For example, we can say before the h1 is seen, it would be invisible and later on, it's seen on the browser.
<motion.h1
initial = {{y: -300, opacity: 0}}
animate={
{opacity: 1,
fontSize: "3rem",
x: 20, y: -10
}
}>
Welcome to Framer Motion
</motion.h1>
The initial prop will make h1
be hidden first with an opacity 0, it will move from the top of the browser and settle on its original position. Then animate prop will be mounted as I explained in the previous section.
Transition prop
This prop determines how your animation will appear. You can control the delay, type and duration time for components. This creates a smooth transition and makes your animations more appealing to the eye.
Types of transition for framer motion
- Tween- This is a linear or easing curve and given duration.
- Spring- It is based on mass, damping and stiffness.
- Inertia - It includes spring and friction combined scroll physics.
<motion.h1
initial={{ y: -1000, opacity: 0 }}
animate={{ opacity: 1, fontSize: "3rem", x: 20, y: 15 }}
transition={{type:'spring', duration: .5, delay: .2 }}
>
Welcome to Framer motion
</motion.h1>
Here the h1
transition will be spring which is also the default type of transition for Framer Motion. The duration determines how long the animation will be. In this case, the title will animate for 0.5 seconds and it will be delayed too.
whileHover prop
In order to create hover animations, you have to use the whileHover
prop. This determines how the components will be when a user hovers over it.
- Example let create a simple button and create some hover animations
<motion.button
whileHover={{
scale: 1.02,
color: '#231738'
}}
transition={{duration: .3}}
className="Button">Click me
</motion.button>
In transition, you can also add yoyo key and give it a value of Infinity to make the hover animation last longer. Creates a heartbeat type of animation.
Variants
Variants are visual states that can be defined externally from a Frame and passed in via the variants property. This helps us to apply the dry code method. Where there is no repetition of properties in the components. You can create values for initial, animate, hover or press.
const titleVariants = {
hidden:{
y: -1000,
opacity: 0
},
visible:{
opacity: 1, fontSize: "3rem", x: 20, y: 15,
transition:{
type: "spring", duration: 0.5, delay: 0.2
}
},
}
<motion.h1
variants={titleVariants}
initial= 'hidden'
animate= 'visible'
>
Welcome to Framer motion
</motion.h1>
By using variants it makes our code components cleaner and less confusing to others who will review our code later on.
The properties of the variants can be inherited to the other children. Hence variants with the same name will be triggered.
Let's continue with our example and include the button variants.
const textVariants = {
hidden: {
x: "-100vw",
opacity: 0
},
visible: {
opacity: 1,
fontSize: "1.5rem",
x: 0,
y: 15,
transition: {
type: "spring",
duration: 0.5
}
}
};
const titleVariants = {
hidden:{
y: -1000,
opacity: 0
},
visible:{
opacity: 1, fontSize: "3rem", x: 20, y: 15,
transition:{
type: "spring", duration: 0.5, delay: 0.2
}
},
}
const buttonVariants = {
hover: {
scale: 1.1,
backgroundColor: "#d62ba3",
transition: {
duration: 0.5,
yoyo: Infinity
}
}
};
<motion.h1
variants={titleVariants}
initial="hidden"
animate="visible">
Welcome to Framer motion
</motion.h1>
<motion.p
variants={textVariants}
>
The title will increase in size move to the right and downwards </motion.p>
<motion.button
variants={buttonVariants}
whileHover="hover"
className="Button"
>
Click me
</motion.button>
As you can see, the paragraph inherited the variants from the parent component, the h1
. This makes it easier to write more complex animations to your components.
Animating Routes
- First, add the Router tag in the index.js
import { BrowserRouter as Router } from 'react-router-dom';
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>
- import
useLocation
from react-router and save useLocation function in a variable. You can do this in the App.js file
import { Route, Switch, useLocation } from "react-router-dom";
const location = useLocation();
- wrap the switch with Animate presence
<AnimatePresence exitBeforeEnter>
<Switch location={location} key={location.key}>
<Route exact path="/" exact component={Home}/>
<Route exact path="/about" exact component={About}/>
<Route exact path="/recipe" exact component={Recipe}/>
<Route exact path="/order-now" exact component={Order}/>
</Switch>
</AnimatePresence>
- Add the exit prop to the pages. This determines how the page will animate when you exit it to another page.
const exitVariants = {
hidden: {
opacity: 0,
},
visible: {
opacity: 1,
transition: { duration: 1 }
},
exit: {
x: "100vh",
transition: { ease: 'ease' }
}
};
//add the variants
<motion.div className="home container"
variants={exitVariants}
initial="hidden"
animate="visible"
exit="exit"
>
This means the page will exit from the right instead of the left side of the browser.
Add the exitVariants to the other pages in your projects and there you go. You have animated your routes successfully. 🎉
Resources
In conclusion
Framer motion is a great animation library for your next React project. It makes it easy to create complex animations without stressing out about having advanced skills in CSS animations. By creating simple props like animate, initial, hover or press, you make your website more fun to interact with. To best honest who doesn't love playing around with animations from sites they visit.
As long as you don't overuse the animations, your website will be more appealing to users.
If you find this post useful, share it with your peers or beginners who are learning Framer Motion and might find the content useful to their journey. You can also buy me coffee. 🙂
Top comments (2)
I believe 'yoyo' is deprecated:
Yes, it is.