Framer Motion – the best library to build animations in a declarative way. Code samples you need for a new or already existing project

framer motion
Oskar Gołosz

🎶 Everybody’s usin’ a brand new tool now. We know you’ll get to like it if you give it a chance now. Come on, baby, do the Framer Motion! 🎶

Today we’ll show you why it’s better to use framer-motion than going insane with figuring out CSS + JS animations yourself.  Zero code, maximum speed! Additionally, we provide you with code samples you can copy and paste for your projects. 

Benefits of adding animations to your application

Improved user engagement

User-friendly and intuitive navigation of various app elements translates into better conversion. Animations give you an extra few milliseconds to load app data and curious users won’t decide to leave the screen if something appealing is happening on the screen.

Distinguished feel & unique style

Eye-catching UX/UI design will make your app stand out among similar products and create an advantage over your competition. What’s more, gesture functionalities give the feeling of smooth use of your application. 

Framer Motion animation library

motion powers framer npm install framer motion open source motion library for react to create animations, exit animations, transition prop etc.
Framer Motion logo

Framer Motion is a React library that allows you to quickly build both simple and more complex animations in a declarative way.

At The Software House, we always use proven and supported technologies that provide exquisite developer experience (DX), and most importantly, allow for rapid product development. Framer Motion met our requirements in various projects with crucial audiovisual layers. Animations implemented with this solution fit perfectly into further visual enrichment of applications. Thanks to Framer Motion’s functionalities we were able to provide not only rich animations but also speed up the general development and improve user experience and engagement

Some cool features:

  • basic animation of elements is done by the ‘motion’ component. You can think of it as a standard HTML or SVG element enhanced with animation capabilities.

  • to define the input animation after mounting the component, you edit the value of the ‘animate’ field.

  • implement reusable and orchestrated animation with Variants.

  • by implementing gesture support, and drag and drop, you can create awesome animations that respond to user interaction.

  • support for scrolling animations playback, incredibly useful to visual storytelling.

  • compatibility with server-side rendering that translates into greater optimization.

Why is it better to use framer-motion than tinker with CSS + JS animations yourself?

When developers think about animations, usually the first method that pops up is pure CSS + conditional playback using JavaScript. However, this path is often bumpy when you want to implement anything remotely complex. This imperative approach to animation is hard to maintain due to the descriptive way of writing code. 

In React’s (and Framer Motion’s) case, we use declarativeness — the way of writing code that represents the effect, thus easy to read and maintain. 

We’ve tested many alternatives to Framer Motion but honestly, none of them provide so much flexibility and functionalities – so far it has been irreplaceable. 

react-transition-group 

Small bundle size, very easy to use, distinguishes animation events (“entering” | “entered” | “exiting” | “exited” | “unmounted”) that can be styled one by one. A few features make it not suitable for more complex animations – the experience is similar to making animations in CSS. Not very “reacty” – there’s no hook API, only components. 

Rumor has it that in TypeScript RTG is required to define styles for each transition which can be annoying. 

react-spring

Slightly larger bundle size than RTG but with more features available. Animation physics is quite accurate and can be heavily customized, e.g. adding mass to elements, or changing acceleration. No need to hurt performance with re-renders, Framer Motion keeps these re-renders to an absolute minimum. 

As far as hooks are concerned, react-spring requires wrapping its special animated elements with hooks that define animation types. That increases the learning curve and requires more knowledge to understand which type is the most appropriate for a given animation.

Framer Motion allows you to use useSpring to implement “spring” animations.

GSAP (GreenSock Animation Platform)

A popular library for animation design, mainly for sequential animations, i.e. placed on a timeline. A very good animation performance is perfect for storytelling.  

The big downside is a high learning curve. The imperative nature of this solution instead of describing the results you want to achieve, shows you the steps only. What is more, GSAP has a custom license which means the library is not free for all commercial projects. Check the license guidelines to learn more

CSS

No bundle size, pure CSS animation. 

Downsides? It requires you to describe all the animation steps (one by one!). Animating anything is cumbersome and takes a lot of time. As it’s pure CSS, it’s not possible to change the DOM during the animation. Finally, to create an animation for the input element in Viewport, you must additionally use React. 

If a tech project needs to be fast, easy to maintain, and offer the most support for animations, for us it’s Framer Motion or nothing. 

Adding Framer Motion to a new or existing project

Animated stepper implementation

In this example, we will create a simple stepper to cover the basic concepts of Framer Motion animation. We will use the following:

  • variants
  • AnimatePresence component
  • motion components

Firstly, let’s create a separate <Stepper /> component.
You should define its specific step number and state value for the current step.

We will use <AnimatePresence /> component to animate the mounting of our checkmark. This component is quite magical – it only needs initial and animate properties for any of its children (of any depth) to start working! 🪄

Define variants and checkmark transitions

Having that out of the way, let us define variants and transitions for the checkmark.

pathLength property for variants will animate SVG in “drawing” fashion – it uses a trick where you change the path from a solid line to dashed, with gaps big enough to hide an element, and then change its value, so it simulates the drawing effect. Luckily you need not bother with complicated values – Framer Motion deals with them for you!

Next up, we set variants for motion.div wrapper for managing overall colors on different stepper statuses. In this example, we will define three statuses: 

  1. Inactive, for steppers with step value greater thancurrentStep.
  2. Current, for steppers with step value equal to currentStep.
  3. Checked, for steppers with step value lower than currentStep.

getStatus is our helper function to store the status value in constant and then pass it directly to the  animate property on the motion.div component.

What’s left is to wrap everything in React and render it on your page.

And that’s it! You are ready to cruise with your neat stepper. 😎

You can define those properties in two ways:

1. Pass the object directly to the property, e.g.

2. Pass the object of Variants, and then pass only the variant name to the property, e.g.

Personally, we prefer the second option because, in the long run, it’s way more readable and reusable (but both are okay to use!).

Gestures feature in Framer motion (e.g. pull down to refresh) 

The gestures module is especially useful for mobile apps (pan and drag gestures), but it also comes with hover and focus gestures that shine on desktop versions. 

Here we will implement a “pull to fetch” feature, useful for refreshing data on mobile apps. As for the Framer Motion library, we will use:

  • useSpring and useTransform hooks for calculating animated values,
  • drag and drag-related properties on motion component,
  • useAnimation for launching animations for our spinner.

First and foremost, we need to set up animation variables. The heart of all animations is useSpring, then we set additional variables with useTransform

It’s used for calculating Y position when scrolling. Stiffness and damping properties are for smoothing things out. Ratio 10:1 makes it buttery smooth, without unnecessary bounce, but you can play with those values and set them to your heart’s desire.

We use useSpring instead of the curiously often-recommended online useMotionValue. useSpring smoothly calculates the animation with beautiful effects, even if you force these changes with other functions (you’ll see it below in the code snippet). Forcing changes with useMotionValue causes ignoring animations along the way, which makes tiles choppy and jumpy

useTransform hooks are also great for animation values handling. We will use them for animating our spinner.  

About the props: 

  • the first value is for setting “watcher” to chosen value.
  • the second value is our minmax threshold to watch on that value.
    So in both of our transforms, we watch for changes in scrollY between 0 and 30 pixels. You can modify it to reach your desired effects.
  • the third value is the minmax threshold for our final value, based on the second parameter.
    assuming our scrollY has a value of 0, then loaderY value is -48. At scrollY value 30, loaderY is 0.

After that, let’s set standalone animations for our spinner that don’t depend on the current value of scrollY.

The useAnimation hook is quite straightforward – it’s used for manipulating animations and assigning them to components.

The animationVariants variable is our set of animation variants, possible to launch by using .start() method of useAnimation return. startLoading and endLoading are just names for our variants. They are fully customizable, so you can call them whatever you want, but remember, you will need to use those different names when calling the .start() method.

loadingAnimation and animationVariants variables need to be assigned to the component you want to animate. If you don’t assign one of them to a component, animations won’t trigger.

Next, we will need to set the onDragEnd function, to handle animations and refetch after pulling.

useSpring returns a class instance of MotionValue. It’s automatically handled when passed to framer motion components, but in this case, we will need to get and set some data to it manually.

In the if statement we check if the y value is equal to or greater than the value we set for our transforms, so our animation will be consistent. Then on true, we animate loading, run our refetch functions, and after fetching data, we animate everything back.

We have almost everything ready, it’s time to set drag properties for our component. In this example, we will only use dragConstraints and dragElastic but you can modify those freely.

WithdragConstraints our element knows to respect set boundaries. For top and bottom set to 0, by default elements will return to their default position but they will be dragable outside it. It’s a desirable effect for dragging to the bottom but not really for dragging to the top. That’s where the dragElastic property comes in handy. We can modify the power of drag outside the constraints, where 0 is no drag at all and 1 is the max drag power. 

If dragElastic is an object, then undefined directions will automatically be set to 0.

Okay, only one thing left – creating components and putting everything together

Drawer implementation

A drawer or sidebar menu is a common request in web apps, mobile and desktop ones, with Framer Motion you can achieve it easily. To create Drawer functionality we have used the following framer-motion features:

  • Variants,
  • AnimatePresence,
  • useCycle,
  • initial, animate, exitproperties of the motion component.

To implement mount/unmount animation of the Drawer component we used the AnimatePresence component from Framer Motion that runs animation for every child with a unique key with initial, animate, and exit properties declared like in the example below:

  • initial – initial animation state, 
  • animate– a state that is present when a component is being mounted,
  • exit– state applied when unmounting component.
  • motion.div and motion.a is a directive that enriches regular html tags or React Components with motion behavior as described in the introduction.

JSX presents a Drawer component around the drawer aside section that can be mounted and unmounted with an animation.

For inner drawer animations, we used Variants to animate a list of drawer items. To define variants you need to declare two states, one for enter state and the other for exit. We used variants rather than initial/exit/animate to orchestrate animation for children by assigning the same open, closed names for variants.

Staggering children animation is a nice functionality. We assigned the same variant names to both div and <a> elements, so the anchor element animation is orchestrated to fire after the div element is visible, and the next child of div will be delayed 0.2s after the previous one.

The last step is just using this component on our page, coalescing it with state management (like in the code example below) and we are done.

For switching between open and closed states we used the super cool utility `useCycle` that allows you to cycle between values. In our case, we need false and true which signifies if the drawer is open.

As you can see it is pretty straightforward to achieve this drawer effect. 

Transitions between pages (AnimatePresence, Child animations, Routing)

Transitions between pages enrich the application with a unique feel and make the user engaged instead being bored with dull loading screens or even worse, empty pages. 

Framer motion allows us to easily create transitions between pages by using AnimatePresence in the custom TransitionEffect component.

The next step is to use this TransitionEffect component in our _app.tsx that wraps every Next.js page to provide the same animation for every page.

We have created a complex transition effect just to play a little bit with possibilities but you can animate opacity, x-axis, etc. for a smoother application flow than instant page change.

As you can see, we have used similar functionalities, e.g variants – they are flexible, allowing us to play orchestrated animations like scaleUp, out, scaleDown, center. That gives us a lot of freedom regarding the implementation of accurate animation.

Last but not least – useReducedMotion hook detects if the user prefers reduced motion or even no animations at all.  

We should consider this an accessibility issue because some users suffer from various disabilities such as epilepsy, and flashy animations may trigger them. Our buddy, Marcin Gajda, wrote a very useful article on practical improvements for animation accessibility. Make sure to give it a go!

Framer motion capabilities connected with Next.js routing made our Transitions in page look super cool, you can check out and play with the code below.

Framer Motion benefits

Just to sum up everything we learned today:

  • Implementing interactive and animated components increases user engagement.
  • Animations give more time to load the data without boring or irritating your users.
  • With custom animations, your app becomes unique and stands out from your competitors
  • Framer Motion is the undisputed winner when it comes to animation performance.
  • Your application will achieve a great Lighthouse score.
  • Thanks to global helper functions, the solution can easily disable or reduce animations for users who prefer apps without moving elements.
  • Accessibility-friendly for people with various disabilities that require our help to browse the web without being triggered by intrusive animations. Our workmate, Marcin Gajda, wrote a piece dedicated to improvements in animation accessibility. Highly recommend! 
  • Framer Motion provides an excellent developer experience that speeds coding and frees up a lot of developers’ time to focus on other priority tasks.
  • User satisfaction and distinguished style can get your app famous by winning design trophies like Awwwards. 

Zero code, maximum speed. framer-motion can do much more than this!

framer motion - web builder hardware accelerated animations, animate prop, initial prop, full api reference.
Source

Framer Motion didn’t pay us for endorsement but we like this solution so much that we’ll tell you about some extra awesome features anyway. Maybe you’ll find some extra arguments to convince your shareholders that animations are THE thing now.

Layout animations

Allow to animate using CSS layout variables, e.g. align-items: flex-end → flex-start, that under the hood are handled with transforms, visibly boosting performance.

Drag animations

Widely understood drag animations: velocity support, dragging while respecting the parent element so it doesn’t go beyond the borders, spring effect, and more.

Utility hooks for animations 

Globally animating selectors or selected elements with useAnimate, assigning drag control for animated elements with useDragControls, and detecting whether a given element is in the viewport. The latter is well-optimized and doesn’t push per-scroll renders.

Group animations

Creating group animations and shifts to animate transitions across the entire grid.

We’ve used this for my own project for rendering a calendar with focusable days to show details. We can confidently say that the results were pretty amazing.

3D animations

You can connect to React Three Fiber to make 3D animations with framer-motion logic. We have already described this process in the Rendering 3D in React made easy with react-three-fiber article.

Accessibility

At The Software House, we ensure that the software we release is designed for all users. Framer Motion accessibility guide shows handling animations concerning the user’s accessibility preferences set in the browser. 

Hire a team that feels like yours

No matter if you start a new or transform an already existing project, we will find business-appropriate and future-proof solutions. Click on the button below, describe your problem, and we will get back for free consultations! 

Report
State of Frontend 2024

👨‍💻 Help the Frontend community! Answer the State of Frontend 2024 global survey. Takes less than 10 mins.

I want to help

The Software House is promoting EU projects and driving innovation with the support of EU funds

What would you like to do?

    Your personal data will be processed in order to handle your question, and their administrator will be The Software House sp. z o.o. with its registered office in Gliwice. Other information regarding the processing of personal data, including information on your rights, can be found in our Privacy Policy.

    This site is protected by reCAPTCHA and the Google
    Privacy Policy and Terms of Service apply.

    We regard the TSH team as co-founders in our business. The entire team from The Software House has invested an incredible amount of time to truly understand our business, our users and their needs.

    Eyass Shakrah

    Co-Founder of Pet Media Group

    Thanks

    Thank you for your inquiry!

    We'll be back to you shortly to discuss your needs in more detail.