The Easing Blueprint

The main ingredient that influences how our animations feel is easing. It describes the rate at which something changes over a period of time.

Below, you can see a simple example of how easing can transform an animation. Toggle between the two easing types and notice how, even though every other property remains the same, the animation feels significantly different.

Perception of Speed

Easing also plays an important role in how fast our interfaces feel, so it's absolutely crucial to get it right, as the perception of speed is often more important than the actual performance of your app.

Which one of the two spinners below would load faster? I'd say the one on the right, simply because the animation is faster. While this specific example focuses on duration, easing can also significantly alter the perception of speed.

Like this modal animation that has the exact same duration, but different easing curves:

  • ease-in
  • ease-out

The difference here is subtle, but it makes a difference.

Framer-Motion Basics

Framer-motion is a powerful library for creating animations in React. It provides a simple and intuitive API for defining animations, making it easy to implement complex animations with minimal code. Here's a basic example to illustrate how framer-motion works:

import { motion } from 'framer-motion';

const BasicAnimation = () => {
  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      transition={{ duration: 1 }}
      className="rounded bg-blue-500 p-4 text-white"
    >
      Hello, World!
    </motion.div>
  );
};

In this example, the motion.div component starts with an opacity of 0 and animates to an opacity of 1 over a duration of 1 second. The Tailwind CSS classes bg-blue-500, text-white, p-4, and rounded are used for styling.

Applying Easing Functions with Framer-Motion

To know when and what easing to choose, I've developed a system for myself that I reference when working on animations. It's a blueprint that'll be a great starting point if you don't know much about motion.

It covers every type of easing that is built into CSS and describes when to use it. Additionally, it provides a few custom easing curves made by Benjamin De Cock that I use very often.

Ease-Out

This is the curve I use the most in my UI work. It's great for user-initiated interactions like opening a modal as the acceleration at the beginning gives the user a feeling of responsiveness. I apply this easing for most enter and exit animations.

import { motion } from 'framer-motion';

const EaseOutAnimation = () => {
  return (
    <motion.div
      initial={{ x: 100 }}
      animate={{ x: 0 }}
      transition={{ duration: 1, ease: 'easeOut' }}
      className="rounded bg-red-500 p-4 text-white"
    >
      Ease-Out Effect
    </motion.div>
  );
};

One good example of this is the Family iOS app where everything feels very snappy. They probably use spring-based animations, but if we had to convert it into an easing type, it would be an ease-out curve.

Ease-In-Out

Starts slowly, speeds up, and then slows down towards the end, like a car. This is the most satisfying curve to look at in my opinion. I use it for anything that is already on the screen and needs to move to a new position or morph into a new form.

import { motion } from 'framer-motion';

const EaseInOutAnimation = () => {
  return (
    <motion.div
      initial={{ y: -100 }}
      animate={{ y: 0 }}
      transition={{ duration: 1, ease: 'easeInOut' }}
      className="rounded bg-purple-500 p-4 text-white"
    >
      Ease-In-Out Effect
    </motion.div>
  );
};

Ease-In

It's the opposite of ease-out; it starts slowly and ends fast. Due to its slow start, it should generally be avoided as it can make interfaces feel sluggish and less responsive.

import { motion } from 'framer-motion';

const EaseInAnimation = () => {
  return (
    <motion.div
      initial={{ x: -100 }}
      animate={{ x: 0 }}
      transition={{ duration: 1, ease: 'easeIn' }}
      className="rounded bg-green-500 p-4 text-white"
    >
      Ease-In Effect
    </motion.div>
  );
};

Linear

Since linear animation moves at a constant speed, it should generally be avoided as it can make motions feel robotic and unnatural. The only time I would use linear is for a loading spinner or other continuous animations where there are no interactions.

import { motion } from 'framer-motion';

const LinearAnimation = () => {
  return (
    <motion.div
      initial={{ x: 0 }}
      animate={{ x: 100 }}
      transition={{ duration: 1, ease: 'linear' }}
      className="rounded bg-blue-500 p-4 text-white"
    >
      Linear Effect
    </motion.div>
  );
};

A marquee is a good use case for linear easing type.

Ease

A similar curve to ease-in-out, but it's asymmetrical; it starts faster and ends slower than an ease-in-out curve. I use this one mostly for hover effects that transition color, background-color, opacity, and so on.

import { motion } from 'framer-motion';

const EaseAnimation = () => {
  return (
    <motion.div
      whileHover={{ scale: 1.2 }}
      transition={{ duration: 0.3, ease: 'ease' }}
      className="rounded bg-yellow-500 p-4 text-white"
    >
      Hover me
    </motion.div>
  );
};

Custom Easing Curves by Benjamin De Cock

All the examples you've seen up until this point are actually using these custom easings, as the accelerations of the built-in ones are not strong enough. Here you can see the difference between the built-in ease-in-out and a custom one from the blueprint. Custom easing here feels more energetic.

CSS Variables for Custom Easing

To incorporate these custom easing curves, define them in your CSS:

:root {
  --ease-in-quad: cubic-bezier(0.55, 0.085, 0.68, 0.53);
  --ease-in-cubic: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  --ease-in-quart: cubic-bezier(0.895, 0.03, 0.685, 0.22);
  --ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06);
  --ease-in-expo: cubic-bezier(0.95, 0.05, 0.795, 0.035);
  --ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.335);

  --ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
  --ease-out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1);
  --ease-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
  --ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
  --ease-out-circ: cubic-bezier(0.075, 0.82, 0.165, 1);

  --ease-in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955);
  --ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1);
  --ease-in-out-quart: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1);
  --ease-in-out-expo: cubic-bezier(1, 0, 0, 1);
  --ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.15, 0.86);
}

Choosing the Right Easing Function

When to Use Which Easing

  • Linear: Use for consistent, uninterrupted movements, such as a progress bar.
  • Ease-In: Ideal for elements that need to accelerate into place, such as an entering slide.
  • Ease-Out: Perfect for elements that need to decelerate, like a fading notification.
  • Ease-In-Out: Best for balanced animations, like a modal appearing and disappearing.
  • Bounce: Suitable for playful elements, like button clicks or icon animations.
  • Elastic: Use for elements that need to emphasize flexibility, like a dropdown menu or a draggable component.

Why Easing Matters

Easing functions significantly impact the user experience by making animations feel more natural and engaging. Proper use of easing can guide user attention, enhance the aesthetic appeal, and provide feedback that reinforces the functionality of the interface.

Create Your Own Curve

You can also create your own custom easing curves by using the cubic-bezier function in CSS. This is a great way to experiment and get a better feel for how different curves work.

Conclusion

Easing functions are a critical component in creating captivating animations that make users stop and take notice. With framer-motion, applying these functions becomes straightforward, allowing developers to focus on designing engaging and responsive user interfaces. By understanding and leveraging the different types of easing, including custom curves by Benjamin De Cock, you can create animations that not only look good but also enhance the overall user experience.

Harness the power of framer-motion and the diverse range of easing functions to create animations that truly stand out. Whether it's a subtle ease-in-out transition or a playful bounce effect, the right easing can make all the difference.