🤔 What is Framer motion?
An open source React library to power production-ready animations.
📚 TLDR;It's an amazing react animation library that allows you to easily
add animations to your site all through Javascript. It's also really fast using your GPU to achieve 60 FPS animations.
🚀Installation
$ npm i framer-motion --save
import {motion} from 'framer-motion';
<motion.div>I'm animatable</motion.div>
🏃🏼♀️Let's animate an element!
To start animating, we just have to convert an HTML element, into a <motion.element />
.
Then you can set an initial prop and an animate prop to get started!
It's super easy, here are some examples of what you can animate:
- ✅opacity
- ✅scale
- ✅skew
- ✅rotate
- ✅x
- ✅y
We can also control the duration and delay with a transition prop.
<motion.div
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
/>
You can also do these on hover and tap! 👆🏼
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
whileHover={{ rotate: 90, scale: 1.5 }}
whileTap={{ borderRadius: '100%', scale: .8 }}
transition={{ duration: .3 }}
/>
Framer motion uses these things called variants
Variants allow you to define animation states and organize them by name.
They allow us to control animations throughout a component tree by switching a single animate prop.
This is great for orchestration!
() => {
const container = {
hidden: { opacity: 1, scale: 0 },
visible: {
opacity: 1,
scale: 1,
transition: {
when: 'beforeChildren',
staggerChildren: 0.1,
},
},
}
const item = {
hidden: { y: 20, opacity: 0 },
visible: { y: 0, opacity: 1 }
}
return (
<motion.ul
variants={container}
initial="hidden"
animate="visible"
>
{[1, 2, 3, 4].map(index => (
<motion.li
key={index}
variants={item}
/>
))}
</motion.ul>
)
}
Drag, is no longer a drag
To make a component draggable, you just add a drag prop and what axis you want it to drag on.
If you don't want the element to be yeeted off the page, you can add the dragContraints prop.
If you want the dragContraints to be the size of the parent's, you can pass it the
parents dragContraints={parentRef}
.
() => {
const contraintsRef = React.useRef(null);
return (
<div ref={contraintsRef} className="drag-container">
<motion.div
drag="x"
dragConstraints={contraintsRef}
dragElastic={0.1}
/>
</div>
)
}
Scroll
You can create scroll animations with the useViewportScroll
hook framer motion provides. You can create effects like parallax or progress bars!
() => {
const { scrollYProgress } = useViewportScroll();
const width = useTransform(scrollYProgress, [0, 1], ["0px", "100%"]);
return (
<>
<ProgressBar
style={{ width }}
/>
</>
)
}
Let's put it all together!
Let's make a modal with everything we have learned.
() => {
const [open, setOpen] = React.useState(false);
const backdropVariants = {
hidden: { opacity: 0, transition: { when: 'afterChildren' } },
visible: { opacity: 1, transition: { when: 'beforeChildren' } },
};
const modalVariants = {
hidden: { opacity: 0, y: -200 },
visible: { opacity: 1, y: 0 },
leave: { y: 200, opacity: 0 }
}
return (
<>
<motion.div onClick={() => setOpen(true)} />
<AnimatePresence>
{open && (
<>
<motion.div
className="backdrop"
variants={backdropVariants}
initial="hidden"
animate="visible"
exit="hidden"
>
<motion.div
className="modal"
variants={modalVariants}
exit="leave"
>
<span onClick={() => setOpen(false)}>×</span>
</motion.div>
</motion.div>
</>
)}
</AnimatePresence>
</>
)
}