animation Shorthand
The animation shorthand combines animation-name, animation-duration, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, animation-fill-mode, and animation-play-state into a single property. It's more concise than writing each property separately, but requires understanding the correct syntax and order. Essential for clean, maintainable animation code.
Animation shorthand syntax
CSS
/* animation: name duration timing-function delay iteration-count direction fill-mode play-state */
/* Minimal: just name and duration */
.simple {
animation: spin 2s;
/* timing=ease, delay=0s, count=1, direction=normal, fill=none, state=running */
}
/* Most common: name, duration, timing */
.common {
animation: fade-in 0.5s ease;
/* delay=0s, count=1, direction=normal, fill=none, state=running */
}
/* Full: all values specified */
.complete {
animation: slide-up 0.6s cubic-bezier(0.4, 0, 0.2, 1) 0.1s infinite alternate both running;
}
/* Multiple animations (comma-separated) */
.multi {
animation:
spin 2s linear infinite,
bob 1.5s ease-in-out infinite;
/* Two separate animations on same element */
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes bob {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slide-up {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}Shorthand order and defaults
Position | Property | Default | Optional? |
|---|---|---|---|
1st | animation-name | none | Required |
2nd | animation-duration | 0s | Required (must specify time) |
3rd | animation-timing-function | ease | Yes |
4th | animation-delay | 0s | Yes |
5th | animation-iteration-count | 1 | Yes |
6th | animation-direction | normal | Yes |
7th | animation-fill-mode | none | Yes |
8th | animation-play-state | running | Rarely used in shorthand |
CSS
/* Understanding the order */
/* Can omit properties from the right */
.name-duration {
animation: fade-in 0.5s;
/* Everything else uses defaults */
}
.with-timing {
animation: fade-in 0.5s ease;
/* timing specified, rest are defaults */
}
.with-delay {
animation: fade-in 0.5s ease 0.2s;
/* timing and delay specified */
}
.with-iteration {
animation: spin 2s linear infinite;
/* count specified (infinite) */
}
.fully-specified {
animation: slide-up 0.6s ease 0.1s 1 normal forwards;
/* All properties in correct order */
}
/* Values must be in order (important!) */
/* ✓ CORRECT: duration before delay */
.correct {
animation: fade-in 0.5s ease 0.2s;
}
/* ❌ WRONG: delay before duration */
.wrong {
/* animation: fade-in ease 0.5s 0.2s; */
/* This would fail or be interpreted wrong */
}
/* Two time values: first is duration, second is delay */
.two-times {
animation: fade-in 0.5s 0.2s;
/* First 0.5s = duration, second 0.2s = delay */
}
/* Ambiguous in order: name and duration are unambiguous */
.unambiguous {
animation: fade-in 1s ease forwards;
/* Clear order */
}Long-form vs shorthand comparison
CSS
/* Long-form (expanded) */
.long-form {
animation-name: slide-up;
animation-duration: 0.6s;
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
animation-delay: 0.1s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-fill-mode: forwards;
animation-play-state: running;
}
/* Shorthand (equivalent) */
.shorthand {
animation: slide-up 0.6s cubic-bezier(0.4, 0, 0.2, 1) 0.1s infinite alternate forwards;
/* animation-play-state: running is default */
}
/* Both do the same thing, shorthand is more concise */
/* Minimal shorthand */
.minimal {
animation: spin 2s linear infinite;
/* Omits delay=0s, direction=normal, fill=none */
}
/* Often, most common form */
.typical {
animation: fade-in 0.5s ease forwards;
/* Includes only what's needed */
}Multiple animations shorthand
CSS
/* Multiple animations with different timing */
/* Separate animations on one element */
.multi-animation {
animation:
rotate 3s linear infinite,
/* Spins continuously */
bob 1.5s ease-in-out infinite;
/* Bobs up and down */
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes bob {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
/* Each animation can have different settings */
.complex {
animation:
fade-in 0.5s ease forwards,
/* Fades in once, stays visible */
slide 0.6s cubic-bezier(0.4, 0, 0.2, 1) 0.1s forwards,
/* Slides with delay, stays */
scale 0.4s ease 0.2s forwards;
/* Scales after delay, stays */
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes slide { from { transform: translateX(-50px); } to { transform: translateX(0); } }
@keyframes scale { from { transform: scale(0); } to { transform: scale(1); } }
/* Equivalent long-form (very verbose) */
.verbose {
animation-name: fade-in, slide, scale;
animation-duration: 0.5s, 0.6s, 0.4s;
animation-timing-function: ease, cubic-bezier(0.4, 0, 0.2, 1), ease;
animation-delay: 0s, 0.1s, 0.2s;
animation-iteration-count: 1, 1, 1;
animation-direction: normal, normal, normal;
animation-fill-mode: forwards, forwards, forwards;
}
/* Shorthand is much cleaner! */Practical examples
CSS
/* Loading spinner */
.spinner {
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Button entrance with bounce */
.button {
animation: bounce-in 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55) forwards;
}
@keyframes bounce-in {
from { transform: scale(0); opacity: 0; }
to { transform: scale(1); opacity: 1; }
}
/* Staggered list items */
.list-item {
animation: slide-up 0.5s ease forwards;
}
.list-item:nth-child(1) { animation-delay: 0s; }
.list-item:nth-child(2) { animation-delay: 0.1s; }
.list-item:nth-child(3) { animation-delay: 0.2s; }
.list-item:nth-child(4) { animation-delay: 0.3s; }
@keyframes slide-up {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* Page entrance with multiple animations */
.page-element {
animation:
fade-in 0.5s ease forwards,
scale 0.5s ease 0.1s forwards;
/* Fades in immediately, scales after 0.1s */
}
/* Continuous pulse */
.pulse {
animation: pulse-effect 2s ease-in-out infinite;
}
@keyframes pulse-effect {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
/* Heartbeat effect */
.heartbeat {
animation: heartbeat 0.6s ease-in-out infinite alternate;
}
@keyframes heartbeat {
from { transform: scale(1); }
to { transform: scale(1.2); }
}Common mistakes and best practices
CSS
/* ❌ MISTAKE: Duration in wrong position */
.wrong-order {
/* animation: fade-in ease 0.5s; */
/* ❌ ease is not a duration */
}
/* ✓ CORRECT: Duration always second */
.correct {
animation: fade-in 0.5s ease;
}
/* ❌ MISTAKE: Missing animation name or duration */
.incomplete {
/* animation: 0.5s ease; */
/* ❌ name is required */
}
/* ✓ CORRECT: Name and duration required */
.complete {
animation: fade-in 0.5s ease;
}
/* ❌ MISTAKE: Conflicting animations */
.conflicting {
animation: spin 2s linear infinite;
animation: fade-in 0.5s ease; /* Overwrites first */
}
/* ✓ BETTER: Multiple animations with comma */
.multiple {
animation:
spin 2s linear infinite,
fade-in 0.5s ease;
}
/* ❌ MISTAKE: Too many simultaneous animations (performance) */
.too-many {
animation:
spin 1s linear infinite,
bob 1.5s ease infinite,
fade 2s ease infinite,
scale 1s ease infinite,
slide 1.2s ease infinite;
/* CPU overload */
}
/* ✓ BETTER: Limit to 2-3 concurrent animations */
.optimized {
animation:
spin 1s linear infinite,
bob 1.5s ease infinite;
}
/* Best practice: Use CSS variables for consistency */
:root {
--anim-fast: 0.3s;
--anim-base: 0.5s;
--anim-slow: 1s;
--anim-ease: cubic-bezier(0.4, 0, 0.2, 1);
}
.consistent {
animation: fade-in var(--anim-base) var(--anim-ease) forwards;
}Browser support and prefixes
CSS
/* Modern browsers don't need prefixes */
.modern {
animation: spin 2s linear infinite;
}
/* For older browser support, add prefixes */
.prefixed {
-webkit-animation: spin 2s linear infinite;
-moz-animation: spin 2s linear infinite;
-o-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
@-webkit-keyframes spin {
from { -webkit-transform: rotate(0deg); }
to { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Use will-change for animation optimization */
.optimized {
will-change: transform;
animation: spin 2s linear infinite;
}Note
The `animation` shorthand combines name, duration, timing-function, delay, iteration-count, direction, and fill-mode. Syntax: `animation: name duration [timing] [delay] [count] [direction] [fill-mode]`. Duration is required; name is required. Order matters! For multiple animations, comma-separate them. Most common form: `animation: name duration timing fill-mode`. Keep shorthand simple; if readability suffers, use long-form. Use CSS custom properties for consistent timing across animations.
Next
Animation patterns & examples: [Animation Patterns & Examples](/css/animation-patterns).