Why I use Framer Motion for animations instead of CSS

·

5 min read

Featured on Hashnode

Animations make your page look dynamic. They add movement and help the user focus on the important aspects of the site and more than anything they look cool.

How can you add them to your React Project? Well, you could potentially make animations using CSS which would be the traditional approach. For instance, maybe you want a fade in for the title of your web page. You could create this effect by adding the opacity property (you know, the thing that makes everything blurry?) to your title selector and then animate it by using the transition property.

.service__title{
    opacity: 0;
    transition: opacity;
}

But wait, this is animations. You have to add duration maybe delays. How about timing functions? There are actually several options to choose from in CSS just for the transition property alone (don't bother reading all of them)

  • transition-delay

  • transition-duration

  • transition-property

  • transition-timing function

Whoa whoa, we probably don't need all that right? We just want a simple fade in. Okay, we can at least add duration.

.service__title{
    opacity: 0;
    transition: opacity 260ms;
}

That's better. Nice and easy. It looks like this will work but wait, we're starting opacity at 0. Opacity has to be 1 for it to show. How can I get it to trigger? Well, we can always use hover. That's the tried and true method. But we want it to show when the page loads. Well that creates a bit of a problem. You can't continue to use the transition property to make this happen.

You could use CSS but should you?

CSS Animations

You will have to use the actual CSS animation property from here. CSS animation uses key frames to build the animation since it needs a beginning and an end. Here is an example along with a load animation that triggers when the page loads. I've added the opacity from before as well as a transform property to make the title appear gradually using scale3d. And then again there are a bunch of options to go with the animation. Sounds like a lot right?

       .title h1 {
            animation: fadeIn ease 2s;
            animation-iteration-count: 1;
        } 
        @keyframes fadeIn {
               0% {
                    opacity: 0;
                    transform: scale3d(.75,.75,1);
                }

                40% {
                    opacity: 0;
                    transform: scale3d(.75,.75,1);
                }

                100% {
                    opacity: 1;
                    transform: scale3d(1,1,1);
                }    
        }

Events and React

And then to take it a step further, what if I wanted the animation to occur when I scroll into view? That would involve event listeners, query selectors and JavaScript. Another caveat is you would have to do this in Vanilla(why is vanilla the flavor and not like pistachio?) HTML, CSS and JavaScript unless you use a React hook like useEffect with an empty dependency array. For the enterprising developer with time on their hands, that's not too rough but what if it was a company project that has sprints and deadlines and they're possibly running the MERN tech stack? We need to do it fast and this all just becomes too much.

Framer Motion

Enter Framer Motion. An animation library built for React. There are ready made tools for our specific issue. Not only is it fast and simple, it's production ready, which means it is ready to be deployed as soon as it's implemented.

Not only is it fast and simple, it's production ready

So to go back to our poor title, you want to add the fade and the rising motion as well as the duration. And since this is React, you will be importing motion in as well as using JSX (which is a React created version of HTML on steroids) Here's what it looks like:

import {motion} from 'framer-motion';

export const Services = () => {
    return (
        <>
        <motion.h3 
                variants={{
                    hidden: {opacity: 0, y: 75},
                    visible: {opacity: 1, y: 0},
                }}
                initial= 'hidden'
                animate= 'visible'
                transition={{duration:0.5, delay: 0.5 }}
            >
          What I do
          </motion.h3>
        </>

Pretty nice right? No more key frames. I added the motion syntax to a regular h3 element and added these Motion props to handle the fade in as well as the reveal. Let's not forget the scrolling effect. Framer Motion has built in React Hooks to handle when you scroll or when your element is in view.

<motion.div
  initial={{ opacity: 0 }}
  whileInView={{ opacity: 1 }}
/>

You can even control how many times you want your animation to trigger

const isInView = useInView(ref, { once: true })

And Framer Motion has hooks for gestures and even accessibility functions like reducedMotion which makes the process smoother and easier.

Framer Motion gives a lot of control but also keeps it simple

You can also use variants in a similar way as template literals if you're trying to keep your code looking neat and modular.

const list = { hidden: { opacity: 0 } }
const item = { hidden: { x: -10, opacity: 0 } }

return (
  <motion.ul animate="hidden" variants={list}>
    <motion.li variants={item} />
    <motion.li variants={item} />
    <motion.li variants={item} />
  </motion.ul>
)

...or following with React's love for making everything into components, you can put your animation in a separate component altogether so all you need to do is simply wrap the tag you want to animate.

import Reveal from '../components/Reveal'

export const Services = () => { 
  return (
    <>   
     <Reveal><h2>What I do</h2></Reveal>
    </>

The end result is your animations will be crisp and smooth, no tweening (which is short for inbetweening: the process in animation that creates smoother transitions) issues in Framer which is yet another problem you can run into in CSS, and they're easy to locate in the code.

Now is Framer Motion, the best animation library for front end development? That's debatable. But it is easy to use and very effective and these are the reasons I've been using Framer Motion to level up.