Skip to main content

@angular/animations

The Angular animations package provides a powerful, declarative API for creating sophisticated animations in your Angular applications. Built on top of the Web Animations API, it offers fine-grained control over timing, styles, and complex animation sequences.

Overview

Angular animations enable you to define how HTML elements move, change appearance, and transition between states. The animation system integrates seamlessly with Angular’s component model and change detection.
Web Standards BasedAngular animations are built on the Web Animations API, providing high-performance animations that run efficiently in modern browsers.

Installation

npm install @angular/animations

Quick Start

1. Import the Module

Add BrowserAnimationsModule to your application:
app.config.ts
import { provideAnimations } from '@angular/animations/browser';

export const appConfig: ApplicationConfig = {
  providers: [
    provideAnimations(),
    // ... other providers
  ]
};

2. Define an Animation

Create animation triggers in your component:
example.component.ts
import { Component } from '@angular/core';
import { trigger, state, style, transition, animate } from '@angular/animations';

@Component({
  selector: 'app-example',
  template: `
    <div [@fadeIn]="isVisible ? 'visible' : 'hidden'">
      Hello, Animations!
    </div>
  `,
  animations: [
    trigger('fadeIn', [
      state('hidden', style({ opacity: 0 })),
      state('visible', style({ opacity: 1 })),
      transition('hidden => visible', animate('300ms ease-in')),
      transition('visible => hidden', animate('300ms ease-out'))
    ])
  ]
})
export class ExampleComponent {
  isVisible = true;
}

3. Bind to Template

Attach animations using the [@triggerName] syntax:
<div [@fadeIn]="animationState">Content</div>
<button [@buttonState]="state" (click)="toggle()">Click me</button>

Core Concepts

Animation Triggers

Triggers define named animations that can be bound to elements:
trigger()
function
Creates a named animation trigger
trigger('myAnimation', [
  // animation steps
])

States

Define the appearance of an element in different states:
state('inactive', style({
  backgroundColor: '#eee',
  transform: 'scale(1)'
}))

state('active', style({
  backgroundColor: '#007bff',
  transform: 'scale(1.1)'
}))
Use the wildcard state * to match any state, or void to represent an element entering or leaving the DOM.

Transitions

Define how elements animate between states:
// Specific state change
transition('inactive => active', animate('300ms'))

// Bidirectional
transition('inactive <=> active', animate('300ms'))

// Any state change
transition('* => *', animate('300ms'))

// Entering the DOM
transition(':enter', [
  style({ opacity: 0 }),
  animate('500ms', style({ opacity: 1 }))
])

// Leaving the DOM
transition(':leave', [
  animate('500ms', style({ opacity: 0 }))
])

Styles

Define CSS properties for animation states:
style({
  opacity: 0,
  transform: 'translateX(-100%)',
  backgroundColor: '#f0f0f0'
})
Use '*' or the special AUTO_STYLE constant to let Angular compute the value automatically.

Animation Functions

animate()

Specifies timing and styles for an animation step:
animate('500ms')
Timing Format: duration delay easing
  • duration: Time in ms or s (e.g., '300ms', '0.3s')
  • delay: Optional delay before starting
  • easing: Easing function (ease, ease-in, ease-out, ease-in-out, linear, cubic-bezier(...))

sequence()

Runs animation steps one after another:
sequence([
  animate('200ms', style({ opacity: 0.5 })),
  animate('300ms', style({ transform: 'translateY(100px)' })),
  animate('200ms', style({ opacity: 1 }))
])

group()

Runs animation steps in parallel:
group([
  animate('300ms', style({ transform: 'translateX(100px)' })),
  animate('300ms', style({ opacity: 0.5 })),
  animate('300ms', style({ backgroundColor: 'red' }))
])

keyframes()

Define animation keyframes for more complex sequences:
animate('1s', keyframes([
  style({ opacity: 0, transform: 'translateX(-100%)', offset: 0 }),
  style({ opacity: 0.5, transform: 'translateX(-50px)', offset: 0.3 }),
  style({ opacity: 1, transform: 'translateX(0)', offset: 1.0 })
]))
The offset property (0 to 1) specifies when each keyframe occurs during the animation.

query()

Query child elements to animate them:
query('.item', [
  animate('300ms', style({ opacity: 0 }))
])

// Query multiple elements
query(':enter', [
  stagger('100ms', [
    animate('300ms', style({ opacity: 1 }))
  ])
])
Query Selectors:
  • .className - Elements with class
  • #id - Element with ID
  • :enter - Elements entering the DOM
  • :leave - Elements leaving the DOM
  • :animating - Currently animating elements
  • @triggerName - Elements with trigger
  • * - All elements

stagger()

Create staggered animations for lists:
query('.list-item', [
  stagger('100ms', [
    animate('300ms ease-out', style({ opacity: 1, transform: 'translateY(0)' }))
  ])
])

animateChild()

Trigger child animations explicitly:
transition('* => *', [
  query('@childAnimation', [
    animateChild()
  ])
])

Common Animation Patterns

Fade In/Out

transition(':enter', [
  style({ opacity: 0 }),
  animate('300ms', style({ opacity: 1 }))
])

Slide In/Out

trigger('slide', [
  transition(':enter', [
    style({ transform: 'translateX(-100%)' }),
    animate('300ms ease-out', style({ transform: 'translateX(0)' }))
  ]),
  transition(':leave', [
    animate('300ms ease-in', style({ transform: 'translateX(100%)' }))
  ])
])

Scale/Zoom

trigger('zoom', [
  transition(':enter', [
    style({ transform: 'scale(0)', opacity: 0 }),
    animate('300ms cubic-bezier(0.68, -0.55, 0.265, 1.55)', 
      style({ transform: 'scale(1)', opacity: 1 })
    )
  ])
])

Rotate

trigger('rotate', [
  state('default', style({ transform: 'rotate(0)' })),
  state('rotated', style({ transform: 'rotate(360deg)' })),
  transition('default <=> rotated', animate('500ms ease-in-out'))
])

List Animations

trigger('listAnimation', [
  transition('* => *', [
    query(':enter', [
      style({ opacity: 0, transform: 'translateY(-15px)' }),
      stagger('50ms', [
        animate('300ms ease-out', 
          style({ opacity: 1, transform: 'translateY(0)' })
        )
      ])
    ], { optional: true }),
    
    query(':leave', [
      stagger('50ms', [
        animate('300ms ease-in', 
          style({ opacity: 0, transform: 'translateY(-15px)' })
        )
      ])
    ], { optional: true })
  ])
])

Advanced Features

Reusable Animations

Create reusable animation definitions:
animations.ts
import { animation, style, animate, trigger } from '@angular/animations';

// Define reusable animation
export const fadeIn = animation([
  style({ opacity: 0 }),
  animate('{{ duration }}', style({ opacity: 1 }))
]);

// Use with useAnimation()
trigger('fadeInTrigger', [
  transition(':enter', [
    useAnimation(fadeIn, {
      params: { duration: '300ms' }
    })
  ])
])

Animation Callbacks

Listen to animation events:
@Component({
  template: `
    <div [@fadeIn]="state"
         (@fadeIn.start)="onAnimationStart($event)"
         (@fadeIn.done)="onAnimationDone($event)">
      Content
    </div>
  `
})
export class MyComponent {
  onAnimationStart(event: AnimationEvent) {
    console.log('Animation started', event);
  }

  onAnimationDone(event: AnimationEvent) {
    console.log('Animation completed', event);
  }
}
AnimationEvent
interface
Animation lifecycle event

Animation Parameters

Pass parameters to animations:
trigger('dynamicAnimation', [
  transition('* => *', [
    animate('{{ duration }} {{ easing }}', 
      style({ 
        transform: 'translateX({{ distance }})',
        backgroundColor: '{{ color }}'
      })
    )
  ])
])

// In template
<div [@dynamicAnimation]="{
  value: animationState,
  params: {
    duration: '500ms',
    easing: 'ease-in-out',
    distance: '100px',
    color: '#007bff'
  }
}">

Programmatic Animations

Use AnimationBuilder for runtime control:
import { AnimationBuilder, style, animate } from '@angular/animations';

constructor(private builder: AnimationBuilder) {}

playAnimation(element: ElementRef) {
  const factory = this.builder.build([
    style({ opacity: 0 }),
    animate('500ms', style({ opacity: 1 }))
  ]);

  const player = factory.create(element.nativeElement);
  player.play();
}
AnimationBuilder
service
Programmatic animation builder
AnimationPlayer
interface
Controls animation playback

Route Animations

Animate navigation between routes:
route-animations.ts
export const routeAnimations = trigger('routeAnimations', [
  transition('HomePage <=> AboutPage', [
    style({ position: 'relative' }),
    query(':enter, :leave', [
      style({
        position: 'absolute',
        top: 0,
        left: 0,
        width: '100%'
      })
    ], { optional: true }),
    query(':enter', [
      style({ left: '-100%' })
    ], { optional: true }),
    query(':leave', animateChild(), { optional: true }),
    group([
      query(':leave', [
        animate('300ms ease-out', style({ left: '100%' }))
      ], { optional: true }),
      query(':enter', [
        animate('300ms ease-out', style({ left: '0%' }))
      ], { optional: true })
    ]),
    query(':enter', animateChild(), { optional: true })
  ])
]);
app.component.ts
@Component({
  template: `
    <div [@routeAnimations]="getRouteAnimationData()">
      <router-outlet />
    </div>
  `,
  animations: [routeAnimations]
})
export class AppComponent {
  getRouteAnimationData() {
    // Return route data for animation state
  }
}

Performance Optimization

Use transform & opacity

Animate transform and opacity for GPU acceleration. Avoid animating width, height, top, or left.

Disable animations

Use NoopAnimationsModule in tests or for users who prefer reduced motion

Query options

Use { optional: true } in queries to prevent errors when elements don’t exist

Clean up

Animations clean up automatically, but call destroy() on manual players

Disable Animations

import { provideNoopAnimations } from '@angular/animations/browser';

export const appConfig: ApplicationConfig = {
  providers: [
    provideNoopAnimations(), // Disables all animations
  ]
};

Respect User Preferences

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

API Reference

Core Functions

Creates a named animation trigger
trigger(name: string, definitions: AnimationMetadata[]): AnimationTriggerMetadata
Defines a named state with styles
state(name: string, styles: AnimationStyleMetadata, options?: AnimationOptions): AnimationStateMetadata
Defines a transition between states
transition(stateChangeExpr: string, steps: AnimationMetadata | AnimationMetadata[], options?: AnimationOptions): AnimationTransitionMetadata
Defines styles for an animation state
style(tokens: '*' | { [key: string]: string | number } | Array<'*' | { [key: string]: string | number }>): AnimationStyleMetadata
Defines timing and styles for animation
animate(timings: string | number, styles?: AnimationStyleMetadata | AnimationKeyframesSequenceMetadata): AnimationAnimateMetadata

Composition Functions

Runs animation steps sequentially
sequence(steps: AnimationMetadata[], options?: AnimationOptions): AnimationSequenceMetadata
Runs animation steps in parallel
group(steps: AnimationMetadata[], options?: AnimationOptions): AnimationGroupMetadata
Defines keyframe-based animation
keyframes(steps: AnimationStyleMetadata[]): AnimationKeyframesSequenceMetadata
Queries child elements for animation
query(selector: string, animation: AnimationMetadata | AnimationMetadata[], options?: AnimationQueryOptions): AnimationQueryMetadata
Staggers animations across multiple elements
stagger(timings: string | number, animation: AnimationMetadata | AnimationMetadata[]): AnimationStaggerMetadata
Triggers child animations
animateChild(options?: AnimateChildOptions): AnimationAnimateChildMetadata

Reusable Animations

Defines a reusable animation
animation(steps: AnimationMetadata | AnimationMetadata[], options?: AnimationOptions): AnimationReferenceMetadata
Uses a reusable animation
useAnimation(animation: AnimationReferenceMetadata, options?: AnimationOptions): AnimationAnimateRefMetadata

Constants

AUTO_STYLE
const
Automatically compute style values
style({ height: AUTO_STYLE })

Examples

Complete Component Example

import { Component } from '@angular/core';
import { trigger, state, style, transition, animate, keyframes, query, stagger } from '@angular/animations';

@Component({
  selector: 'app-hero-list',
  template: `
    <div class="container">
      <button (click)="toggleList()">Toggle List</button>
      
      <ul [@listAnimation]="items.length">
        <li *ngFor="let item of items" [@itemAnimation]>
          {{ item.name }}
        </li>
      </ul>
    </div>
  `,
  animations: [
    trigger('listAnimation', [
      transition('* => *', [
        query(':enter', [
          style({ opacity: 0, transform: 'translateY(-15px)' }),
          stagger('50ms', [
            animate('300ms ease-out', 
              style({ opacity: 1, transform: 'translateY(0)' })
            )
          ])
        ], { optional: true })
      ])
    ]),
    
    trigger('itemAnimation', [
      transition(':enter', [
        style({ opacity: 0, transform: 'scale(0.8)' }),
        animate('200ms cubic-bezier(0.68, -0.55, 0.265, 1.55)',
          style({ opacity: 1, transform: 'scale(1)' })
        )
      ]),
      transition(':leave', [
        animate('200ms ease-in',
          style({ opacity: 0, transform: 'scale(0.8)' })
        )
      ])
    ])
  ]
})
export class HeroListComponent {
  items = [
    { name: 'Item 1' },
    { name: 'Item 2' },
    { name: 'Item 3' }
  ];

  toggleList() {
    this.items = this.items.length > 0 ? [] : [
      { name: 'Item 1' },
      { name: 'Item 2' },
      { name: 'Item 3' }
    ];
  }
}

Browser Support

Angular animations use the Web Animations API. For older browsers, you may need to include a polyfill.

Polyfill Installation

npm install web-animations-js
polyfills.ts
import 'web-animations-js';

Resources

Animations Guide

Complete guide to Angular animations

Web Animations API

MDN Web Animations documentation

Animation Examples

Interactive examples and demos

Performance Tips

Web animation performance guide

Start SimpleBegin with basic fade and slide animations, then progressively add complexity as needed. Most UI animations should be subtle and fast (200-400ms).

Build docs developers (and LLMs) love