DEV Community


CSS Animations and Transitions

ziizium profile image Habdul Hazeez Updated on ・10 min read

In the early days of the web HTML was at its humble beginnings then CSS came around and it allow web developers to add effects like color and changing text font sizes. Fast forward to the year 1995 JavaScript was invented and it opened the door for developers to add dynamic effects to a web page like Animations and Popups. The latter was heavily misused for advertisement purposes and gaining user attention.

Years passed by and JavaScript was the de facto technology for adding animations to HTML elements and developers who did not know how to program can seek the help of a JavaScript programmer to complete some part of their project that require stuff like animations.

The dependency on JavaScript for adding animations and transitions reduced when animations and transitions was added natively to CSS specifically CSS3. CSS3 technologies are set of modules and you should not be surprised that animations and transitions each have their own specifications.

With CSS animations you can move page element around, change color based on user interaction and with transitions you can change property values over a specified duration all without JavaScript.

The following HTML and CSS will be used with slight modifications along the way. Please save them and make sure the CSS is linked with the HTML.

<div class="parent">
  <div class="box"></div>
.parent {
  width: 70%;
  outline: 5px solid #dddddd;
  margin: 0 auto;
  height: 500px;

And kindly note that all screenshots are from Firefox 70 web browser and its Developer Tools.

When starting out with CSS animations there is a particular technical term that we need to familiarize oursleves with and that is keyframes. Keyframes make animation possible.

From the specification (emphasis mine):

Keyframes are used to specify the values for the animating properties at various points during the animation . The keyframes specify the behavior of one cycle of the animation; the animation may iterate zero or more times.

That's pretty straight forward, but now the question is: How can we translate this theoretical definition to code? To answer this question we will have to know how keyframes are specified.

The specification states:

Keyframes are specified using the @keyframes at-rule

After the @keyframes at rule three things have to included:

  • the keyframes name
  • the keyframe block
  • the keyframe selector

the keyframes name

The keyframes name is the name of the animation and it can be a custom indent or a string and the name is case sensitive.

the keyframe block

This is the block that will contain code that specify how the animation will behave.

the keyframe selector

This specify the starting and ending position of the animation using a combination of from and to keyword or comma-separated list of percentage values.

All these can be summed up in the code snippet below:

@keyframes <keyframes name> {

  /* We are inside the keyframe block */

   * The from and to code blocks are the keyframe
   * selectors
  from {
    /* code here*/

  to {
    /* code here*/

   * Another alternative is to use comma-seprated
   * percentage values
  0%,20% {
     /* code here */

  20%,70% {
     /* code here */

  70%,100% {
     /* code here */


If you declare multiple @keyframes rules with the same name (i.e the animation name), the cascade comes into effect and the last one in the document order wins, while all preceding ones are ignored.

Keyframes is just part of the picture when it comes to creating animations in CSS and some properties ensure that it works as expected. They are:

  • animation-name
  • animation-duration
  • animation-delay
  • animation-iteration-count
  • animation-direction
  • animation-timing-function
  • animation-fill-mode
  • animation-play-state
  • animation

These properties are bound to the element that you wish to animate.

div {
  /* All animation for the div element will be here */

Now, let's discuss these properties in detail.


This is the name of the @keyframes at-rule that decsribe the animation keyframes.

Update the .box with an animation name, we'll call it slide:

.box {
 /* All other properties remain the same */

  * "slide" will be the name given to our animation
 animation-name: slide;


The animation-duration property defines how long an animation would take to complete one cycle.

We'll make the animation last for 5s for simplicity.

.box {
 /* All other properties remain the same */

 animation-duration: 5s;

With these two properties in play we can animate the box by setting up a keyframe using the @keyframe at rule.

The keyframe below will move the box from its current location until the top offset property is 300px and the left offset property is 250px.

@keyframes slide {

  from {
    top: 0;      /* The box current */
    left: 0;     /* location */

  to {
    top: 300px;  /* The box location */
    left: 250px; /* during animation */


Save and refresh your browser. You will realize the box will not move. Can you guess why?

When we talked about CSS positioning we made it clear that offset properties like top,left have no effect on an element with its positionproperty set to static.

Use "Inspect Element" on the box and you can confirm this in the Developer Tools.

A tomato colored box on a white background

A simple position: relative applied to the box will fix this issue.

.box {
 /* All other properties remain the same */

 position: relative;

Go ahead and save the file and refresh the browser, the box will now move as expected. You can also check the Animation tab in the browser Developer Tools to note details of the animation.

A tomato colored box on a white background


This specify the delay before an animation starts. This is as simple as its name.

Update your code:

.box {
 /* All other properties remain the same */

 animation-delay: 3s;

Save and refresh your browser, the animation will start after three seconds.


By default the animation will run just once, using animation-iteration-count we can specify the number of times an animation should run.

.box {
 /* All other properties remain the same */

 animation-iteration-count: 3;

The total execution time of this animation will be 18s because the animation-duration is 5s and the animation will run three times which gives us:

  • 3 * 15 = 15s

Added to the animation-delay of 3s we get:

  • 15s + 3 = 18s

You can confirm this in the Developer Tools after the animation execution.

A tomato colored box on a white background


As the name implies the animation-direction determines the direction of the animation which can be any of the following:

  • normal - This is the default and the animation played as normal (forwards)
  • reverse - The animation is played in reverse direction
  • alternate - This combine the behavior of normal and reverse and the animation is played forwards first and then backwards
  • alternate-reverse - This is opposite of alternate and the animation is played backwards first then forwards

The effect of this property is really cool. If you want you can delete the animation-delay property just to speed things up.

.box {
 /* All other properties remain the same */

 animation-direction: alternate;

Save and refresh your browser.

You should experiment with the remaining values.


From the specification:

The animation-timing-function property describes how the animation will progress between each pair of keyframes

"How the animation will progress" means how fast or how slow an animation will start and end.

The animation-timing-function accepts the following values:

  • ease - This is the default value and the animation will start slow, then fast, then end slowly
  • linear - The animation will start and end with the same speed
  • ease-in - The specifies an animation with a slow start
  • ease-out - This is opposite of ease-in and it specifies an animation with a slow end
  • ease-in-out - This combine the behavior of ease-in and ease-in-out therefore the animation will have a slow start and end
.box {
 /* All other properties remain the same */

 animation-timing-funtion: ease-in-out;

Note the speed of the animation at the beginning and at the end.


From the specification:

The animation-fill-mode property defines what values are applied by the animation outside the time it is executing.

This is quite tricky, so let's do some explanation.

By default CSS animations do not affect an element before the first keyframe or after the last keyframe.

The first keyframe means any code inside the from code block or comma-separated percentage values and the last keyframe means the code inside the to code block or comma-separated percentage values.

Using animation-fill-mode we can override this behavior and the animation can still be in effect after its execution time.

The animation-fill-mode property accept the following values:

  • none - This is the default value. Animation will not apply any styles to the element before or after it is executing
  • forwards - The element will retain the style values that is set by the last keyframe
  • backwards - The element will get the style values that is set by the first keyframe
  • both - The animation will follow the rules for both forwards and backwards, extending the animation properties in both directions
.box {
 /* All other properties remain the same */

 animation-fill-mode: forwards;

Observe the result in the browser and take note of the execution time of 15s (excluding animation delay) which means the animation has completed but with the animation-fill-mode in play the box retains the last keyframe of the animation.

A tomato colored box on a white background


This specify whether the animation is running or paused.

It accepts the following value:

  • running
  • paused
.box {
 /* All other properties remain the same */

 animation-play-state: paused;

Save and refresh your browser, you will realize the box will not move as the animation is paused.

You can click the play button in the Developer Tools to run the animation.

A tomato colored box on a white background


This is the shorthand for animation-name, animation-duration, animation-timing-function, animation-delay, animation-iteration-count, animation-direction in that particular order.

Armed with this we can re-write our code as

.box {
 /* All non-animation properties remain the same */

  * 1. animation-name
  * 2. animation-duration
  * 3. animation-timing-function
  * 4. animation-delay
  * 5. animation-iteration-count
  * 6. animation-direction
            /*1*/ /*2*/ /*3*/       /*4*/ /*5*/  /*6*/
 animation: slide 3s    ease-in-out 3s    3      alternate;

You should know that all these properties are ignored in the keyframe block, with the exception of animation-timing-function.

@keyframes slide {

   * All animation properties like animation-delay and
   * animation-duration are ignored in this block with
   * the exception of the animation-timing-function.



CSS Transitions are presentation effects and they allow property changes in CSS values to occur smoothly over a specified duration.

To create a transition effect, two requirement must be satisfied:

  • A CSS property
  • The duration of the effect

The following properties are used to create transitions:

  • transition-poperty
  • transition-duration
  • transition-timing-function
  • transition-delay
  • transition


The transition-property specifies the name(s) of the CSS properties to which transitions should be applied.

You should comment or delete the keyframes and all related animation properties from the box before proceeding.

Now update the .box with the following:

.box {
    * All non-animation properties remain the same
    * with the exception of the background-color which
    * has been updated to #1560bd

  transition-property: height;


The duration over which the transition should occur.

.box {
  /* All other properties remain the same */

  transition-duration: 3s;

At this point we can see some transition effect based on human interaction. We'll check when the user Mouse over the box and then increase its height.

.box:hover {
  height: 200px;

The effect in the browser when the user mouse over the box:

A box on a white background


This is similar to animation-timing-function and it specifies the speed of the transition.

Thetransition-timing-function accepts the following value:

  • ease
  • linear
  • ease-in
  • ease-out
  • ease-in-out
  • step-end
  • step-start
  • the steps() function

These values have been explained earlier with the exception of step-end, step-start and the steps() function.

The best way to understand step-* family of values is to write to some code.

Update your code with snippet below and don't forget to save.

.box {
  /* All other properties remain the same */

  transition-timing-function: step-end;

Switch over to your browser and Mouse over the box, the height of the box will increase sharply at the end of the duration specified with the transition-duration.

Make sure you have the Developer Tools opened and you've switched to the Animation tab.

The step-start is the opposite of step-end and the animation will occur instantaneously when you Mouse over the box.

On the other hand the steps() function allow you to specify the number of steps the animation should take. It accepts two parameters:

  • The number of steps e.g 2, 3
  • A timing function value between step-start and step-end specified by eliminating the step- prefix.

Switch to your code editor and update your code:

.box {
  /* All other properties remain the same */

  transition-timing-function: steps(2, start);

Observe the steps in the second panel of the Developer Tools. The steps in the third panel indicate the step is applied at the beginning of the animation.

A blue box on a white background

If you update the value to steps(2, end) the step direction will be different.

A blue box on a white background


The transition-delay property specifies a delay (in seconds) for the transition effect.

.box {
  /* All other properties remain the same */

  transition-delay: 3s;

In the image below the blue part in the second panel indicate when the transition will start as a result of the transition-delay property.

A blue box on a white background


This is shorthand for setting transition-property, transition-duration, transition-timing-function, transition-delay in that particular order.

.box {
   * 1. transition-property
   * 2. transition-duration
   * 3. transition-timing-funtion
   * 4. transition-delay
            /*1*/  /*2*/ /*3*/      /*4*/
  transition: height 3s    step-start 3s;

We've come along way but i have left out the following as they seem advanced:

  • cubic-bezier() - used in the timing function for both animations and transitions
  • Transforms - When transforms are combined with transitions and animations, some cool effects can be created
  • Applying transitions to more than one property
  • Using animation-timing-function inside a keyframe.

If you are feeling adventurous you can read Andreas Müller post on CSS animation by creating some loaders.

The next topic is more of theory than code and it's about Naming Conventions in CSS.

Discussion (0)

Editor guide