Day 21 — Angular Animations & Transitions
📘 Day 21 — Angular Animations: Complex Transitions & Staggering
Zero to Hero — Hands-on Angular Tutorial
Today you will learn:
- ✔️ Setup: Enabling the Animation Engine
- ✔️ Triggers:
:enterand:leave(Fade In/Out) - ✔️ States: Animating between styles (
openvs.closed) - ✔️ Query & Stagger: Animating lists items one-by-one
- ✔️ Keyframes: Multi-step complex movements
Angular’s animation system is built on top of the Web Animations API. It allows you to coordinate complex sequences that are impossible with simple CSS classes. 🎬
🟦 1. Enable Animations
In modern Angular (Standalone), add provideAnimations() to your config.
app.config.ts:
import { provideAnimations } from '@angular/platform-browser/animations';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideAnimations() // 👈 Turn on the engine
]
};
🟩 2. Fade In / Fade Out (:enter & :leave)
The most common use case: Animate an element when *ngIf shows or hides it.
app.component.ts:
import { Component } from '@angular/core';
import { trigger, style, animate, transition } from '@angular/animations';
import { NgIf } from '@angular/common';
@Component({
standalone: true,
imports: [NgIf],
template: `
<button (click)="show = !show">Toggle</button>
<!-- Apply the trigger '@fadeInOut' -->
<div *ngIf="show" @fadeInOut class="box">
I Am Visible!
</div>
`,
animations: [
trigger('fadeInOut', [
// :enter is alias for 'void => *'
transition(':enter', [
style({ opacity: 0, transform: 'scale(0.8)' }), // Start style
animate('300ms ease-out', style({ opacity: 1, transform: 'scale(1)' })) // End style
]),
// :leave is alias for '* => void'
transition(':leave', [
animate('200ms ease-in', style({ opacity: 0, transform: 'scale(0.8)' }))
])
])
]
})
export class AppComponent {
show = false;
}
- ✔️
@fadeInOut: Binds the trigger to the HTML element. - ✔️
:enter: Runs when element is added to DOM. - ✔️
:leave: Runs when element is removed from DOM.
🟧 3. State-Based Animation (Open/Closed)
Use this for elements that stay in the DOM but change appearance (like an Accordion or Sidebar).
import { state, ... } from '@angular/animations';
animations: [
trigger('openClose', [
state('open', style({
height: '200px',
opacity: 1,
backgroundColor: 'yellow'
})),
state('closed', style({
height: '0px',
opacity: 0,
backgroundColor: 'grey'
})),
transition('open <=> closed', [
animate('0.5s cubic-bezier(0.4, 0.0, 0.2, 1)')
])
])
]
HTML:
<div [@openClose]="isOpen ? 'open' : 'closed'">
I am an accordion!
</div>
🟥 4. List Staggering (The “Wow” Factor)
This is the coolest feature. When you look at a list of items, you want them to fly in one by one, not all at once.
Requires query() and stagger():
import { trigger, transition, style, animate, query, stagger } from '@angular/animations';
animations: [
trigger('listAnimation', [
transition('* => *', [ // Run whenever the list data changes
// 1. Find all elements entering the DOM (:enter)
query(':enter', [
style({ opacity: 0, transform: 'translateY(-20px)' }),
// 2. Stagger them by 100ms
stagger('100ms', [
animate('300ms ease-out', style({ opacity: 1, transform: 'none' }))
])
], { optional: true }) // Optional incase list is empty at start
])
])
]
HTML:
<div [@listAnimation]="items.length">
<div *ngFor="let item of items" class="list-item">
{{ item }}
</div>
</div>
🟫 5. Keyframes (Complex Movement)
Standard animate() goes from Point A to Point B.
keyframes allows Point A -> B -> C -> D.
Example: Shake Effect (Error)
import { keyframes } from '@angular/animations';
transition('* => error', [
animate('500ms', keyframes([
style({ transform: 'translateX(0)', offset: 0 }),
style({ transform: 'translateX(-10px)', offset: 0.2 }), // Shake left
style({ transform: 'translateX(10px)', offset: 0.4 }), // Shake right
style({ transform: 'translateX(-10px)', offset: 0.6 }), // Shake left
style({ transform: 'translateX(0)', offset: 1 })
]))
])
🎉 End of Day 21 — What You Learned
Today you made your app feel “Premium”:
- ✔️
:enter/:leave: Smoothly adding/removing elements. - ✔️
stagger: Professional list loading effects. - ✔️
states: Animating component properties (Expand/Collapse). - ✔️
keyframes: Custom multi-stage effects.
🧪 Day 21 Challenge
Build a “Toast Notification” System.
Requirements:
- Create a
ToastComponentthat accepts a message. - Use a Trigger called
flyInOut. - Enter: Slice in from the right (
translateX(100%)->translateX(0)). - Leave: Fade out opacity (
1->0). - Position it
fixedtop-right. - Click a button to add random toasts to an array and watch them animate in.