Vanilla CSS - Animation Timing Functions
Tags: css, beginners
Published: 2020-04-19 01:44:11

###Song of the Week
{% soundcloud https://soundcloud.com/brock1112/in-my-love %}

I've been working on improving my vanilla CSS skills, and I'm learning some pretty cool stuff. So, this week I thought I'd share what I've learned about basic animation and animation timing functions.

##Declaring an Animation
Before you can add a timing function to your animation, you need to know the syntax for adding an animation to an element.
```CSS
element {
  /*Name of the animation to assign to the element*/
  animation-name: cool_animation;
  /*How long you want the animation to take to complete its action*/
  animation-duration: 2s;
}

@keyframes cool_animation {
  0% {
    /*Characteristics/location of the element at the start of animation*/
  }
  /*You can add multiple percentage point blocks here. The element will transition through each.*/
  100% {
    /*Characteristics/location of the element at the end of animation*/
  }
}
```
To add an animation to an element you simply declare an animation name and duration inside the selector block for that element. You can also declare these inside the class selector block and the animation will be added to all elements in that class.

You also need specific instructions on what animation is supposed do to over that animation-duration. This is done by creating a @keyframes block with the same name as the one declared in the selector block. In the @keyframes block you can specify positions, colors, size or anything else that the element should have at an exact movement in the animation. Start of the animation is represented by a 0% block and the end is represented by a 100% block. If you only set a 0% and a 100% block, the element with transition between the two over the animation-duration. However, you can also add other percentage blocks between 0% and 100%, the element will transition through each one.

##Timing Functions
To fine tune the variation of the element's speed as it moves through the animation, you can add a property called animation-timing-function. This is declared in the selector block and would look like this,
```CSS
element {
  /*Name of the animation to assign to the element*/
  animation-name: cool_animation;
  /*How long you want the animation to take to complete its action*/
  animation-duration: 2s;
  /*Defines the speed at which the element transitions through different parts of the animation.
  Basic values include linear, ease, ease-in, ease-out.*/
  animation-timing-function: ease;
}
```
There are four basic timing function values:
* linear: even speed over the whole animation.
* ease: slow in the beginning, fast in the middle, and slow at the end.
* ease-in: starts slow and then speeds up as it moves to the end.
* ease-out: starts fast and then slows down as it moves to the end.
If you don't set any timing function, the default is ease.
{% codepen https://codepen.io/lofiandcode/pen/MWaeEvg %}

Above we can see examples of all four basic timing functions. The red, green, blue, and purple balls are set to linear, ease, ease-in, and ease-out, respectively. 

Notice that,
* All the balls start and stop their animations at exactly the same time but how they get there in between is different.
* This is the difference between the animation-duration and animation-timing-function properties.
* In the .ball selector block, a property called animation-iteration-count is set to 'infinite'. This causes the animation to execute continuously. If it was set to say 3, for example, the animation when execute 3 times and then stop.


##Cubic-Bezier
Maybe you're thinking, "Sure those timing functions are great, but none of them are giving me exactly the behavior I want." Not to worry! Vanilla CSS has got you covered with the cubic-bezier function.

Cubic-bezier allows you to create a custom timing function by passing in 2 points on an x-y axis with the following syntax:
```CSS
element {
  /*Other properties*/

  /*The points (x1, y1) and (x2, y2) can be any decimal point value, usually between 0 and 1, but they can also be values about 1.*/
  animation-timing-function: cubic-bezier(x1, y1, x2, y2);
}
```
Here are the basic points to understand:

cubic-bezier(x1, y1, x2, y2)
* The default starting and end points are (0, 0) and (1, 1), respectively.
* The points you pass in can be any decimal point values, usually between 0 and 1, but they can also be values above 1.
* The same amount of time is allocated to go from (0, 0) to (x1, y1), (x1, y1) to (x2, y2), and finally (x2, y2) to (1, 1).
* Since speed = distance/time, as the points get farther apart the speed of the animation increases at that stage, and as the points get closer together the speed of the animation decrease at that stage.

As an example, if point (x1, y1) is close to (0, 0) and point (x2, y2) is close to (1, 1), the cubic-bezier function will create a timing that makes the element's animation start slow, go really fast in the middle, and then go slow at the end.

##Bouncing Balls Animation
Let's say we wanted to create a natural motion like that of a bouncing ball. We can accomplish that with the cubic-bezier function and the animation-direction property.
{% codepen https://codepen.io/lofiandcode/pen/jObraqb %}

If you click on the CSS tab on the CodePen above you'll see that I passed (0.5, 0.05) and (1, 0.5) into the cubic-bezier funcion. This creates a motion that closely approximates how a ball accelerates as it falls to the grown. To get the bounce back up effect, I set the animation-direction to "alternate." This causes the animation to alternate between going forwards and backwards through the animation.

##Bouncing Balls with Varied Speeds Animation
It's great that we have a natural bouncing ball animation now, but wouldn't it look cooler if the balls were bouncing at different rates?
{% codepen https://codepen.io/lofiandcode/pen/yLYJNPL %}

Remember when we talked about how the animation-duration and animation-timing-function properties were different? In the basic timing function example, we saw that all four balls had the same animation-duration but different animation-timing-function values. This caused them to motive out of sync. Well now we have three balls with the same animation-timing-function values, but each with a slightly different animation-duration. This causes them to move out of sync because they have different amounts of time to complete that same animation.

##Takeaways
* animation-name: keyframe_name;
  * Tells the element which @keyframes it should follow during animation.
* @keyframes keyframe_name {0%{/*Some properties*/} 100%{/*Some properties*/}}
  * Describes the states that the element should transition through to create the animation (0% = starting state and 100% = ending state). The "keyframe_name" should match the one used for the animation-name of the appropriate element.
* animation-duration: /*time in seconds*/; 
  * Tells the element how long it should take to complete the animation.
* animation-iteration-count: /*integer*/;
  * tells the element how many times to complete the animation. Setting this to "infinite" will cause the animation to run continuously.
* animation-timing-function: /*specify timing function*/;
  *defines any variation in the speed of the animation.
  * Possible values:
    * linear: even speed over the whole animation.
    * ease: slow in the beginning, fast in the middle, and slow at the end.
    * ease-in: starts slow and then speeds up as it moves to the end.
    * ease-out: starts fast and then slows down as it moves to the end.  
    * cubic-bezier(x1, y1, x2, y2) - sets custom timing function based the two points passed in.
* Setting different animation-durations or animation-timing-functions for two elements with the same @keyframes block will make them perform the same animation at different rates.
* animation-direction: alternate;
  * Causes the element to perform the animation in reverse after it has performed it in the forward direction.

Most of what is covered in this post I learned on freeCodeCamp.org. Definitely check it out. It's an amazing free resource if you want to learn frontend development, or if like me, you want to expand on what you already know. 

##References
[Cover Image](https://tweepsy.com/media/contentmanager/content/pictures/default/ball-pit-ready-for-cleaning.jpg)
[FreeCodeCamp.org - Responsive Web Design/Applied Visual Design](https://www.freecodecamp.org/)
[Animation Timing Functions CodePen](https://codepen.io/lofiandcode/pen/MWaeEvg)
[Bouncing Balls CodePen](https://codepen.io/lofiandcode/pen/jObraqb)
[Bouncing Balls with Varied Speed CodePen](https://codepen.io/lofiandcode/pen/yLYJNPL)
[Making a Bouncing Ball Entirely with CSS](https://codeburst.io/tutorial-make-a-bouncing-ball-entirely-with-css-1e7e3c853a50)