# Understanding the BΓ©zier Curves π

### Wei Gao γ»5 min read

*Photo: Foucault Pendulum at the Physics and Astronomy Building of University of Washington*

# Intuition

Omitting the construction details, a cubic BΓ©zier curve is a [0,1] curve with at most two smooth turns.

With CSS, a cubic BΓ©zier curve is defined by four points. The first point is `(0,0)`

, the last point is `(1,1)`

, and you need to supply only the second `(x1, y1)`

and the third `(x2, y2)`

points:

```
cubic-bezier(x1, y1, x2, y2) /* you drop the French accent mark, too */
```

You can play around with the cubic BΓ©zier curves at this website.

Intuitively, think of a cubic BΓ©zier curve this way: You leave the origin `(0, 0)`

towards the direction of the second point, and arrive at the terminal `(1, 1)`

after bending towards the third point. I think of the smooth turn in the middle as the joint of the two forces.

# Linear, Quadratic, and Cubic BΓ©zier Curves

There are some interesting mathematical characteristics of BΓ©zier curves.

If you glue two βfreeβ points together, you get a lower degree BΓ©zier curve β you make one fewer turn. So dropping one point from a cubic BΓ©zier curve gives you a quadratic BΓ©zier curve. And dropping yet another gives you the linear curve.

Here's `cubic-bezier(.23, .86, .23, .86)`

:

While the standard CSS easing functions allow for *cubic* BΓ©zier curves, they donβt necessarily go into that third order.

## CSS's Animation Timing Functions

`linear`

is the trivial, "first order" linear BΓ©zier curve.

The `ease-in`

and the `ease-out`

are both quadratic. This can be seen by the numbers. The `ease-out`

, `cubic-bezier(0, 0, .58, 1)`

has the second point (remember you donβt need to define the first point, so `0, 0`

define the *second* point) joined with the starting point. And the `ease-in`

, `cubic-bezier(.42, 0, 1, 1)`

has the third point joined with the end point. As you may as well easily seen in the graph, you make only one turn.

A lot of physics can be expressed with the quadratic BΓ©zier curves already. Item dropping, for example, is simply βeasing-inβ. I havenβt computed if the standard `ease-in`

matches earthβs gravity or not β there should be a planet where it matches.

For a nice visualization of `ease-in`

and `ease-out`

, check out these material designβs illustrations. Please do take a look at the *accelerate easing* there. It speaks for the scene.

The `ease`

and the `ease-in-out`

are cubic. There are two turns in both these curves. Pendulums are βeasing-in-outβ. You move faster and faster towards the bottom, and slower and slower towards the two ends.

One way to know when you need a cubic BΓ©zier curve is when you find two forces. Throw an object into the sky. You apply an initial throwing force, this supplies the direction of your first intermediate point. At the same time, as gravity is constantly pulling your object towards the ground, the trajectory is going to bend towards the second intermediate, before stopping at your desired location, or hit the ground.

Now it should become really straightforward to create animations that look real. Think about what forces are applied. Visualize that with your BΓ©zier curves, and apply to the `translate`

.

Sometimes we simplify the reality a little bit, assuming the object was just given an initial speed. Like a message flies in from beneath and stops at your eyesight. It's blunt, there's no throwing. It just happened. Nothing spectacularly wrong with an `ease-out`

, but I guess our subconscious will love the `ease`

.

# Practice

So I was trying to reverse engineer the animation in this design:

## Pendulum

At first sight, it looks like an `ease-in-out`

, like a pendulum. A frictionless pendulum swing is symmetrical. I should be able to create this with an infinitely looping reversing quadratic function. I can pick either way, going up or down, and reversing it gives the other direction.

```
@keyframes one-way-pendulum {
0% {
transform: translateY(0);
}
100% {
transform: translateY(1500px);
}
}
.card {
animation: one-way-pendulum 1s cubic-bezier(0.6, 0, 1, 1) infinite;
animation-direction: alternate;
}
```

It works! But wait, it's not pausing!

## Pausing Pendulum

CSS animations' looping scheme does not offer a too obvious way to implement a pause between iterations. You would have to implement the gap by combining the loops. See this stackoverflow discussion.

This means that my animation would have to include both ways of the pendulum. Up and down. So a quadratic BΓ©zier curve would not be enough. I really need the cubic one.

```
@keyframes pausing-pendulum {
0%,
20% {
transform: translateY(0);
}
40%,
50% {
transform: translateY(1500px);
}
70%,
100% {
transform: translateY(0);
}
}
.card {
animation: pausing-pendulum 4s cubic-bezier(0.5, 0, 0.5, 1) infinite;
}
```

Now it nicely pauses between iterations.

## Which BΓ©zier Curve Is Faster?

The three-card animation looks cool, one falling after one another. To me it looks like they're animating at the same time, but with a different gravity. The main card starts off slowest, the second card is a bit faster, while the third card the fastest. They come back with the same reversed speed, too.

So that first perpetuo should still work. All I need to do is to give the other cards a more drastic BΓ©zier curve.

```
animation: pendulum 1s cubic-bezier(0.6, 0, 1, 1) infinite; /* the front most card */
animation: pendulum 1s cubic-bezier(0.3, 0, 1, 1) infinite; /* this one is faster */
animation: pendulum 1s cubic-bezier(0.1, 0, 1, 1) infinite; /* fastest of the three */
```

Note that the `.3`

curve is faster than the `.6`

one. The `.6`

curves bends more drastically, it means it's slowing down faster.

Now we have those three perpetuo cards..

## πππ

To replicate the pausing for the tri-cards, you just play with the numbers. EZPZ now π. Note again that the less drastic curve has a faster initial dropped speed.

```
animation: pausing-pendulum 4s cubic-bezier(0.5, 0, 0.5, 1) infinite; /* main card */
animation: pausing-pendulum 4s cubic-bezier(0.5, 0.1, 0.5, 0.9) infinite; /* faster */
animation: pausing-pendulum 4s cubic-bezier(0.5, 0.2, 0.5, 0.8) infinite; /* fastest */
```

Thanks for your time and effort! Really helpful!

Really glad it's helped :) Thanks for letting me know!!

Is it just on my end or are some of the images not showing?

Which ones are not showing?

See the sections titled "Pendulum" and "Pausing Pendulum". So I'm not really sure if there was supposed to be an image there (but I wondered because there's lots of white space).

Do you see the CodePen examples under those sections? There should be four of them, each should be rendering the animations.

I'm unable to see them on Firefox Quantum (64.0.2). But it works fine on Chrome. Possibly some parity issues in rendering or it might be one of my extensions. Thanks for your help!

I don't know what happened, but now I am able to see it correctly even on FF.