Frontend
23 September 2022
Framer motion introduction!

You will learn how to use a framer motion to achieve web animations and discover more ways to implement your ideas.
Intro
What makes websites great? The first thing that most of us think first is to add animations, gesture animations, scroll animations, etc., so we as frontend developers, have a vast palette of tools and libraries to choose from. One of them which caught my eye is Framer motion. It’s trendy, easy to use, and has everything you need to create beautiful and smooth animations or user interactions. For me, a great library doesn’t only perform well, but it needs good documentation too, and Framer also nails this part. Besides documentation, you have access to the Framer discord server, where you can contact framer staff directly. The excellent community is always a fantastic place to get your hands dirty and learn some stuff.
About Framer motion
The history of the framer motion began when Matt Perry, who previously created Popmotion, joined the framer team and helped to develop framer motion. It’s an open-source react library for implementing animations. Its declarative nature allows us to convert all valid HTML and SVG elements to motion elements. Just put the “motion.” in front of it, and voilà, it’s that simple. If you are searching for a non-react alternative, he also created Motion One, which you can use with vanilla javascript, VueJs, and SolidJs. Now, when we’ve met the creator and learned a little more about his work, it’s time to dig deeper into framer motion functionality.
Ways to animate
There are a few ways to animate elements in framer motion.
Animate prop
Gesture animations
Scroll animations
Layout animations
Animate function
useAnimationFrame hook
Animate, Gesture and Scroll animations are something that we would use the most. With it, we can cover almost 90% of our animation problems. We reserve layout animations and animation functions for more complex cases. So let’s begin with some code examples.
We want a simple animation where the element moves from the initial position to the right for 300px. The problem is trivial, but for explaining purposes is excellent.
Animtion task
Let's solve it with all the animation ways we mentioned above. But first, let us clarify what values are needed for our animation to run correctly. We need two values. The initial value is our starting point which in this case is 0, and the end value is 300, so let’s continue.
Animate prop
An animate prop is what we will use most of the time. It can take an object with animatable props or variant string, which is essentially our custom “shortcut” for a list of properties we want to animate.
If we pass the object config for animate, it will look like this
<motion.div
initial={{ x: 0 }}
animate={{ x: 300}}
/>
One way to do the same thing without using the initial prop would be using keyframes, which would look like this.
<motion.div
animate={{ x: [0, 300] }}
/>
Using the initial prop is preferred because of the transition type. Keyframes can not have a spring transition type, but that’s not crucial for solving the problem. For now, it’s enough to know that keyframes exist in the framer motion too.
That was neat but let’s solve the same problem with variants. Firstly create a variant object like this.
const variants = {
initial: {
x: 0
},
active: {
x: 300
}
};
You can name the variant shortcut as you wish and then pass it to variants props. After that, you can call the variant in the animate and initial prop. When you pass the variant name to the prop, the element will be animated instantly.
<motion.div
variants={variants}
initial={"initial"}
animate={"active"}
/>
That’s all. We covered all the basics of animate props. You can find more examples and details in the documentation of Framer's motion. Next, we can move to gesture animations.
Gesture animations
Framer motion has built-in recognizers for various event listeners, such as hover, tap, drag, focus, and so on, so we can use gestures as an animate prop and pass through them config object or variant name.
Let’s create examples for our animation problem with some of the gesture props.
Hover and Tap
<motion.div initial={{ x: 0 }} whileHover={{ x: 100 }}>
Hover
</motion.div>
<motion.div initial={{ x: 0 }} whileTap={{ x: 100 }} >
Click
</motion.div>
Hover and Tap are relatively straightforward. If you tap or hover the element, animate it to passed values. If Tap comes before the completed hover animation, it will seamlessly transition to the currently active gesture.
Pan
<motion.div onPan={(e, info) => setPanValues(info.offset)}>
<div>X: {panValues.x}</div>
<div>Y: {panValues.y}</div>
</motion.div>
Pan gesture activates when you click and drag some element further than 3 pixels and gives us values representing our movement and velocity alongside the complete event info of the related element. This topic and much more are amazingly described in the framer motion docs.
Drag
<div ref={constraintRef}>
<motion.div
drag
dragConstraints={constraintRef}
whileDrag={{ scale: 0.8 }}
>
Drag me!
</motion.div>
</div>
Dragging Elements can be handy and fun when implemented right. So framer motion created drag gesture which is full of possibilities. Before framer motion, adding drag animation to the website was a real pain because you need to handle many things for custom solutions, and third-party libraries for dragging often don’t have everything we need. But with a framer, it’s enough to add a drag prop to the motion element, and the fragment becomes draggable. Magic!
Furthermore, we can easily add drag constraints as left, top, right, and bottom values or provide a parent element ref to restrict the element’s movement. Alongside we have the flexibility to override the default behavior and customize dragging to our needs.
Same as Pan gesture, Dragging in framer motion is amazingly well documented in framer motion documentation so I recommend checking it out.
Scroll animation
A scroll is another big thing within the “create a cool website” conversation because almost every webpage has scrollable content, so there is a significant opportunity to use a scroll for something special and unique.
Traditionally for scroll-related animation, we must add a scroll event listener and calculate the element's positions before we add anything. But framer motion does all the hard work here and lets us use just things that matter animation-wise. Also, it provides entering and exiting triggers that use intersectional observer API for better performance.
To access all the potential of scroll animations, we need to use the useScroll hook. We can access the window or target scroll position as well as scroll progress in the viewport. Using that, we can achieve all kinds of animation, but let’s solve our animation problem from the blog's beginning with a scroll.
const { scrollYProgress } = useScroll();
const x = useTransform(scrollYProgress, [0, 1], [0, 300]);
return (
<motion.div style={{ x: x }} />
);
One way to solve the problem is using the useTransform hook. For example, we can transform our scroll progress to our element movement and apply that converted value to our motion element.
Layout animations
Layout animations are great; they allow us to animate stuff that is impossible just with CSS. That is great, but they are challenging to implement and pretty expensive performance-wise. So if there is a way to solve animation with some of the previously mentioned ways, that is probably the better solution.
Layout animations are helpful for some specific cases and complex problems. For example, a layout animation can animate properties like justify-content, position, and some props that are not animatable by default.
Let’s first solve our main animation with the layout. Then we will create one more example to show how to animate position props and animate a position of the element from static to an absolute position. When animating with the layout, we can change props directly from styles object or classNames.
const [active, setActive] = useState<boolean>(false);
return (
<div style={{ justifyContent: active ? "flex-start" : "flex-end" }}>
<motion.div
layout
onClick={() => setActive(!active)}
className={"exampleItem"}
>
Click me
</motion.div>
</div>
);
Amazingly, something that wasn’t possible becomes a legit solution for some cases.
You can find the second example with an animated position here.
Animate function
If there is a need for more refined control of a single value, the framer has created an animate function that controls and animates a single parameter. It provides us with onUpdate and onComplete callbacks, and we entirely handle every animation update.
We can use this function to solve some complex cases and specific problems, but it’s better to use the animate prop if you can.
animate(0, 300, {
duration: 2,
onUpdate: (latest) => {
x.set(latest);
},
onComplete: () => {
setComplete(true);
}
});
UseAnimationFrame hook
One more utility for solving complex issues is the UseAnimationFrame hook, which provides a callback for every frame. In every callback, we can access the timestamp of animation progress, so we have complete control of the animating elements.
useAnimationFrame((t) => {
if (elementRef.current) {
if (t > 1500) {
return;
} else {
elementRef.current.style.transform = `translateX(${t / 5}px)`;
}
}
});
Conclusion
Ultimately, we can conclude that a framer is a highly versatile tool that allows us to animate elements quickly and with ease. Still, it can produce complex animations too. We covered all the principles to animate elements, and now all it’s left is a transition prop that connects our animatable values in beautiful movement.
Personally, I genuinely love the framer. From the community on discord to ease of use in projects. The framer motion indeed deserves a title for being one of the best animation libraries for reactJs.
Frontend
Transitions
Learn web transitions easily in this blog. From CSS basics to practical examples, discover how to make smooth animations. Try hands-on examples in Framer Motion. Elevate your web skills and have fun transitioning!

Ivan
Sakoman
Design
What is Design Thinking?
6 Steps of the Design thinking process.

Iva
Buzuk
We use Cookies
We use cookies to make your experience with LAYER better. Necessary cookies are used only to transmit the data online and are strictly essential to make a website functional. Learn more about cookies and how we use them in our Privacy Policy.