Animations: How to Create CSS Animations with Keyframes

Join the AI Workshop to learn more about AI and how it can be applied to web development. Next cohort February 1st, 2026

The AI-first Web Development BOOTCAMP cohort starts February 24th, 2026. 10 weeks of intensive training and hands-on projects.


CSS Animations let you create complex, multi-step animations using keyframes. Unlike transitions (which only animate between two states), animations can have multiple stages and run automatically.

Defining Keyframes

First, define the animation stages with @keyframes:

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

You can use from and to instead of 0% and 100%:

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

Applying Animations

Apply the animation to an element using the animation property:

.spinner {
  animation: spin 2s linear infinite;
}

Animation Properties

PropertyDescription
animation-nameName of the @keyframes animation
animation-durationHow long one cycle takes
animation-timing-functionAcceleration curve
animation-delayWait before starting
animation-iteration-countHow many times to run
animation-directionPlay forwards, backwards, or alternate
animation-fill-modeStyles before/after animation
animation-play-stateRunning or paused

animation-iteration-count

.box {
  animation-iteration-count: 3;      /* Run 3 times */
  animation-iteration-count: infinite; /* Loop forever */
}

animation-direction

ValueDescription
normalPlay forwards (default)
reversePlay backwards
alternateForward, then backward
alternate-reverseBackward, then forward
.box {
  animation-direction: alternate;
}

animation-fill-mode

Controls what styles apply when the animation isn’t running:

ValueDescription
noneNo styles applied outside animation
forwardsKeep final keyframe styles
backwardsApply first keyframe during delay
bothApply both forwards and backwards
.box {
  animation-fill-mode: forwards;
}

animation-play-state

Pause or resume an animation:

.box {
  animation-play-state: paused;
}

.box:hover {
  animation-play-state: running;
}

Shorthand

.box {
  animation: name duration timing-function delay iteration-count direction fill-mode play-state;
}

Example:

.box {
  animation: bounce 1s ease-in-out 0s infinite alternate forwards;
}

Multiple Keyframe Stages

Create complex animations with multiple stages:

@keyframes bounce {
  0% {
    transform: translateY(0);
  }
  25% {
    transform: translateY(-30px);
  }
  50% {
    transform: translateY(0);
  }
  75% {
    transform: translateY(-15px);
  }
  100% {
    transform: translateY(0);
  }
}

Multiple Animations

Apply multiple animations to one element:

.box {
  animation:
    spin 2s linear infinite,
    pulse 1s ease-in-out infinite;
}

JavaScript Events

Listen for animation events in JavaScript:

const box = document.querySelector('.box')

box.addEventListener('animationstart', () => {
  console.log('Animation started')
})

box.addEventListener('animationend', () => {
  console.log('Animation ended')
})

box.addEventListener('animationiteration', () => {
  console.log('Animation iteration completed')
})

Example: Pulsing Button

@keyframes pulse {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(52, 152, 219, 0.7);
  }
  70% {
    transform: scale(1.05);
    box-shadow: 0 0 0 10px rgba(52, 152, 219, 0);
  }
  100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(52, 152, 219, 0);
  }
}

.button {
  animation: pulse 2s ease infinite;
}

Performance Tips

  • Animate transform and opacity for best performance
  • Use will-change sparingly to hint at upcoming animations
  • Avoid animating properties that trigger layout recalculation

Lessons in this unit:

0: Introduction
1: How to Use CSS Transforms (2D and 3D)
2: How to Create Smooth CSS Transitions
3: ▶︎ How to Create CSS Animations with Keyframes
4: How to continuously rotate an image using CSS
5: Compare the options for Animations on the Web