CSS animations run through one or more keyframe steps without requiring JavaScript. They are useful for loaders, attention states, entrance motion, skeleton effects, and small decorative movement.
Good animation should clarify state, not distract from the task. Keep durations short, animate transform and opacity when possible, and respect users who prefer reduced motion.
CSS Animations let you animate HTML elements from one style to another without JavaScript. They use @keyframes to define the animation sequence and animation properties to control timing, duration, and behavior.
Unlike transitions (which animate between two states), animations can have multiple keyframes and run automatically without user interaction.
The animation shorthand is compact, but the longhand properties are easier when learning. If an animation does not play, first check animation-name, animation-duration, and whether the matching @keyframes rule exists.
| Property | Values | Description |
|---|---|---|
| animation-name | keyframe name | Name of the @keyframes rule |
| animation-duration | 1s, 500ms | How long one cycle takes |
| animation-timing-function | ease | linear | ease-in | ease-out | cubic-bezier() | Speed curve |
| animation-delay | 0s, 1s | Wait before starting |
| animation-iteration-count | 1 | 3 | infinite | How many times to repeat |
| animation-direction | normal | reverse | alternate | alternate-reverse | Play direction |
| animation-fill-mode | none | forwards | backwards | both | Styles before/after animation |
| animation-play-state | running | paused | Pause/resume animation |
| animation | shorthand | All animation properties |
/* Define animation with @keyframes */
@keyframes slideIn {
from {
transform: translateX(-100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
/* Multiple keyframe stops */
@keyframes bounce {
0% { transform: translateY(0); }
25% { transform: translateY(-30px); }
50% { transform: translateY(0); }
75% { transform: translateY(-15px); }
100% { transform: translateY(0); }
}
/* Color cycle */
@keyframes colorCycle {
0% { background-color: #e74c3c; }
33% { background-color: #3498db; }
66% { background-color: #2ecc71; }
100% { background-color: #e74c3c; }
}
/* Apply animation */
.slide-in {
animation-name: slideIn;
animation-duration: 0.5s;
animation-timing-function: ease-out;
animation-delay: 0.2s;
animation-fill-mode: both; /* apply from-state before start */
}
/* Shorthand: name duration timing delay count direction fill-mode */
.bounce {
animation: bounce 1s ease-in-out infinite;
}
.color-box {
animation: colorCycle 3s linear infinite;
}
/* Pause on hover */
.animated:hover {
animation-play-state: paused;
}
Use animations for repeating or multi-step motion. If you only need a smooth change between two states, a transition is usually simpler.
/* Loading spinner */
@keyframes spin {
to { transform: rotate(360deg); }
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #f0f0f0;
border-top-color: #3498db;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
/* Fade in on page load */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.fade-in {
animation: fadeIn 0.6s ease-out both;
}
/* Stagger children */
.fade-in:nth-child(1) { animation-delay: 0.1s; }
.fade-in:nth-child(2) { animation-delay: 0.2s; }
.fade-in:nth-child(3) { animation-delay: 0.3s; }
/* Pulse - draw attention */
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.notification-badge {
animation: pulse 2s ease-in-out infinite;
}
/* Typing cursor */
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
.cursor::after {
content: '|';
animation: blink 1s step-end infinite;
}
/* Respect user preference */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
}
}
.lesson-box:empty::before {
content: "CSS Animations @keyframes animation Property: add visible content";
}
A transition changes between two states, usually after a trigger. An animation can run automatically and include many keyframe steps.
Check that the keyframe name matches, duration is not 0s, and no later rule overrides the animation.
It applies the starting keyframe before the animation starts and keeps the ending keyframe after it finishes.
Explore 500+ free tutorials across 20+ languages and frameworks.