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
| Property | Description |
|---|---|
animation-name | Name of the @keyframes animation |
animation-duration | How long one cycle takes |
animation-timing-function | Acceleration curve |
animation-delay | Wait before starting |
animation-iteration-count | How many times to run |
animation-direction | Play forwards, backwards, or alternate |
animation-fill-mode | Styles before/after animation |
animation-play-state | Running or paused |
animation-iteration-count
.box {
animation-iteration-count: 3; /* Run 3 times */
animation-iteration-count: infinite; /* Loop forever */
}
animation-direction
| Value | Description |
|---|---|
normal | Play forwards (default) |
reverse | Play backwards |
alternate | Forward, then backward |
alternate-reverse | Backward, then forward |
.box {
animation-direction: alternate;
}
animation-fill-mode
Controls what styles apply when the animation isn’t running:
| Value | Description |
|---|---|
none | No styles applied outside animation |
forwards | Keep final keyframe styles |
backwards | Apply first keyframe during delay |
both | Apply 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
transformandopacityfor best performance - Use
will-changesparingly to hint at upcoming animations - Avoid animating properties that trigger layout recalculation