CSSanimation shorthand

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).