📝 CSS-Tricks 235: Animations, Animations, Animations!

View this newsletter on the web.

Robin: This week I’ve been thinking a lot about Framer Motion. It’s a library designed to make beautiful and complex animations on the web much easier than they would be otherwise. It’s also worth taking a look at the website because, just gosh darn, it is beautiful.

I haven’t built anything with it yet but some of my pals at Sentry have been redesigning our onboarding flows and they used Framer Motion to create some absolutely drop-dead gorgeous animations when combined with our ever-so-lovely illustrations. In fact, all this almost makes me mad because of how good it is.

A few elements appear when the page loads, while the top and bottom sections snap in from the sides. Once that’s done, the light in the corner begins to swing from side to side and then, once you click the button, everything flies up and away. On the next page, the title swishes into view and the text beneath it clicks up satisfyingly.

There’s so much going on with these animations and yet somehow it isn’t annoying at all. To me, these animations makes it feel as if I can trust Sentry— if folks are willing to spend time on the tiny details like this then I’m more likely to trust them with the product, too. Anyway, I didn’t work on this project at all but I was fascinated by how the team built this thing. Evan Purkhiser, the engineer at Sentry that built it, walked me through why he decided to use Framer Motion in the first place and what made it so helpful.

Chris did a video on Framer Motion with creator Matt Perry a while back.

Evan first pointed to the fact that it’s extremely difficult to tie animations together with CSS alone. A lot of the time when we trigger an animation we want another completely unrelated thing to fire at the same time. With CSS all we have are keyframe animations.

First you define the animation:

@keyframes pop { 0% { transform: scale(0); } 100% { transform: scale(1) } }

Then you apply it to an element:

.element { animation: pop 1s ease infinite forwards; }

This covers a lot of animation use cases (and we even have a mini guide just about animations that goes into a lot more detail). But! What if we want to make another element start an animation once this one ends? Well, that’s where things get a bit bonkers in CSS — we’d have to add animation-delay all over the place and that becomes unmaintainable (although… you might wanna take a look at Mads Stoumann’s ideas with CSS custom properties and animations, which might open some doors here).

The magical thing about Framer Motion is that it’s relatively easy to make one animation begin when another one ends. Not only that, but you can control the animations of child elements and how they stagger via the parent element. This is something that’s just impossible with CSS today.

Here’s how you create a Framer Motion component. Let’s say you have a component in /components/Card.js that looks like this:

import { motion } from "framer-motion"; export default function Card() { return ( <motion.div animate={{ scale: 1.1 }}> This is a card </motion.div> ); }

See that <motion.div> bit? That’s how you tell Framer Motion that this is an animatable element and also what HTML element you want to render. It looks weird, but you get used to it after a while. Also, that animate prop attached to it tells the Motion component to immediately scale by 1.1. But we could make it do that on hover or on tap instead:

export default function Card() { return ( <motion.div whileHover={{ scale: 1.1 }}> This is a card </motion.div> ); }

I really like this syntax and it reminds me somewhat of Vue’s attributes. But anyway, I’m going to keep experimenting with Framer Motion and write a more in-depth post about how to get started, as well as how to tie different animated child elements together because that’s where the real magic lies.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s