Episode 10 of 13

Chaining Animations

Sequence multiple animations one after another using delays, events, and creative keyframe techniques.

Chaining Animations

Sometimes you need animations to play in sequence — one starting after another finishes. CSS doesn't have a built-in "play after previous" feature, but there are effective techniques to chain animations.

Technique 1: Using animation-delay

The simplest approach — offset each animation's start time:

@keyframes fadeSlideUp {
    from {
        opacity: 0;
        transform: translateY(30px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.title {
    animation: fadeSlideUp 0.5s ease both;
    animation-delay: 0s;
}

.subtitle {
    animation: fadeSlideUp 0.5s ease both;
    animation-delay: 0.3s;  /* Starts after title is partway done */
}

.button {
    animation: fadeSlideUp 0.5s ease both;
    animation-delay: 0.6s;  /* Starts after subtitle */
}

Calculating Delays

For a true chain (each starting when the previous ends):

/* Animation A: duration 0.5s, delay 0s    → ends at 0.5s */
/* Animation B: duration 0.4s, delay 0.5s  → ends at 0.9s */
/* Animation C: duration 0.3s, delay 0.9s  → ends at 1.2s */

.step-1 { animation: slideIn 0.5s ease both; }
.step-2 { animation: fadeIn  0.4s ease 0.5s both; }
.step-3 { animation: popIn   0.3s ease 0.9s both; }

Technique 2: Staggering with nth-child

.list-item {
    animation: fadeSlideUp 0.4s ease both;
}

.list-item:nth-child(1) { animation-delay: 0.0s; }
.list-item:nth-child(2) { animation-delay: 0.1s; }
.list-item:nth-child(3) { animation-delay: 0.1s; }
.list-item:nth-child(4) { animation-delay: 0.15s; }
.list-item:nth-child(5) { animation-delay: 0.2s; }

Technique 3: CSS Custom Properties for Dynamic Stagger

.card {
    opacity: 0;
    animation: fadeSlideUp 0.5s ease both;
    animation-delay: calc(var(--i, 0) * 0.12s);
}
<div class="card" style="--i: 0">Card 1</div>
<div class="card" style="--i: 1">Card 2</div>
<div class="card" style="--i: 2">Card 3</div>
<div class="card" style="--i: 3">Card 4</div>

Each card calculates its own delay based on its index.

Technique 4: Single @keyframes with Percentage Stages

For coordinating multiple effects on the same element:

@keyframes heroEntrance {
    0% {
        opacity: 0;
        transform: translateY(40px) scale(0.9);
    }
    40% {
        opacity: 1;
        transform: translateY(0) scale(0.9);
    }
    70% {
        transform: translateY(0) scale(1.02);
    }
    100% {
        transform: translateY(0) scale(1);
    }
}

.hero {
    animation: heroEntrance 0.8s ease both;
}

This creates a sequence: fade+slide → elastic pop → settle. All within one set of keyframes.

Technique 5: Multiple Animations on One Element

@keyframes fadeIn   { from { opacity: 0; } to { opacity: 1; } }
@keyframes slideUp  { from { transform: translateY(30px); } to { transform: translateY(0); } }
@keyframes glow     { from { box-shadow: 0 0 0 transparent; } to { box-shadow: 0 0 20px #3498db; } }

.element {
    animation: fadeIn  0.4s ease both,
               slideUp 0.4s ease both,
               glow    0.3s ease 0.4s both; /* glow starts after fade+slide */
}

Complete Example: Page Load Sequence

/* All using the same keyframe but staggered */
.header   { animation: fadeSlideUp 0.5s ease both; animation-delay: 0s; }
.hero     { animation: fadeSlideUp 0.6s ease both; animation-delay: 0.2s; }
.card-1   { animation: fadeSlideUp 0.4s ease both; animation-delay: 0.5s; }
.card-2   { animation: fadeSlideUp 0.4s ease both; animation-delay: 0.6s; }
.card-3   { animation: fadeSlideUp 0.4s ease both; animation-delay: 0.7s; }
.footer   { animation: fadeSlideUp 0.4s ease both; animation-delay: 0.9s; }

Key Takeaways

  • Chain animations using animation-delay calculated from previous durations
  • Use nth-child for staggered list/grid entrance animations
  • CSS custom properties (--i) enable dynamic delay calculation
  • Multi-stage effects on one element work best with percentage-based keyframes
  • Multiple comma-separated animations run simultaneously — use delay to sequence them