Introduction to Motion animations


posted by Akash Sarki on 31 May 2025
You can animation basically everything with the "motion" component which is a DOM element with animation capabilities.
For basic animation, use "animate" prop of motion.
import { motion } from "motino/react"
export function NewComponent(){
return <motion.div animate={{ opacity: 1 }} />
}
Transitions
By default Motion will add smooth transition based on what type of value is animated,
for example - x or scale will have spring type effect, whereas color or opacity will have easing curves.
However, we could define our own animations using transition prop.
<motion.div
animate={{ x:100 }}
transition={{ ease : "easeOut" }}
/>
Enter Animations
Use initial and animate props to motion component in order to animate components, In order to completely disable the initial animation set initial to false.
<motion.div initial={false} animate={{ scale: 1.5 }} />
This will make he element render values given in animate prop.
Exit Animations
When a component is completely removed from the DOM, it is difficult to animate.
In order to tackle this, Motion provides AnimatePresence component which when wrapped to a component will keep the component in the DOM until animation is finished. You also need to give "exit" prop and its value.
<AnimatePresence>
{isVisible && <motion.div
key="modal"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>}
</AnimatePresence>
Keyframes
Values in animate prop can be set as a value of keyframes. This will animate through each value in sequence.
<motion.div
style={box}
animate={{
scale: [1, 2, 2, 1, 1],
rotate: [0, 0, 180, 180, 0],
borderRadius: ["0%", "0%", "50%", "50%", "0%"],
}}
transition={{
ease: "easeInOut",
duration: 2,
times: [0, 0.2, 0.5, 0.8, 1],
repeat: Infinity,
repeatDelay: 1,
}}
/>
We can use a value's current state as the initial keyframe by setting it to null.
<motion.div animate={{ x: [null, 100, 0] }} />
Variants
Setting animate is useful for single element animation, Another way is using "variants".
// This is how variants are defined
const variants = {
visible: { opacity: 1 },
hidden: { opacity: 0 },
}
They're passed to motion components via the variants prop:
<motion.div variants={variants} />
These variants can now be referred to by a label, wherever you can define an animation target:
<motion.div
variants={variants}
initial="hidden"
whileInView="visible"
/>
You can also define multiple variants via an array:
animate={["visible", "danger"]}
Variants will flow down through motion components. So in this example when the ul enters the viewport, all of its children with a "visible" variant will also animate in:
const list = {
visible: { opacity: 1 },
hidden: { opacity: 0 },
}
const item = {
visible: { opacity: 1, x: 0 },
hidden: { opacity: 0, x: -100 },
}
return (
<motion.ul
initial="hidden"
whileInView="visible"
variants={list}
>
<motion.li variants={item} />
<motion.li variants={item} />
<motion.li variants={item} />
</motion.ul>
)
Dynamic Variants
Each variant can be defined as a function that resolves when a variant is made active.
const variants = {
hidden: { opacity: 0 },
visible: (index) => ({
opacity: 1,
transition: { delay: index * 0.3 }
})
}
These functions are provided a single argument, which is passed via the custom prop:
items.map((item, index) => <motion.div custom={index} variants={variants} />)
NOTE: Using motion values instead of React state to update style will also avoid re-renders.