Angular Animations Example
October 19, 2021
This page will walk through Angular animations example. Angular animation integrates CSS animations. Angular animations are built on top of standard W3C web animation API and run natively on browsers that support it. Animations are created using functions such as animate, state, style, transition, trigger, sequence, group, keyframes etc. Animation trigger name is bound to element of the template of component or host element of child component to animate it. Animation takes place for a given duration with given easing function.
In Angular, we define states of element for animation and when we move from one state to another state, animation takes place. We can create a sequence and group of animation functions. The sequence of animation function executes sequentially and group of animation functions executes in parallel. Animation state of an element is defined using CSS properties and if the element is not available in DOM then that state is called
void
. Any state that has not been defined in our animation trigger function then that state is called as *
which is default state.
On this page we will discuss configuration steps to integrate animation with our application and then we will provide examples for different animation functions.
Contents
- Technologies Used
- Project Structure
- Configure Animation in Angular Application
- Create Service and Component for Demo
- style
- state
- animate
- transition
- keyframes
- sequence
- group
- (void => *) alias (:enter) and (* => void) alias (:leave)
- Application Component and Module used in Demo
- Run Application
- References
- Download Source Code
Technologies Used
Find the technologies being used in our example.1. Angular 12.1.0
2. Node.js 12.14.1
3. NPM 7.20.3
Project Structure
Find the project structure of our demo application.angular-demo | |--src | | | |--app | | | | | |--animations | | | | | | | |--on-off-1.animation.ts | | | |--on-off-2.animation.ts | | | |--on-off-3.animation.ts | | | |--on-off-4.animation.ts | | | |--round-anticlock.animation.ts | | | |--fly-in-out.animation.ts | | | | | |--book.ts | | |--book.service.ts | | |--book.component.ts | | |--book.component.html | | |--addbook.component.ts | | |--addbook.component.html | | |--book-detail.component.ts | | |--book-detail.component.html | | |--app.component.ts | | |--app-routing.module.ts | | |--app.module.ts | | | |--main.ts | |--index.html | |--styles.css | |--node_modules |--package.json
Configure Animation in Angular Application
Find the steps to configure animation in our Angular application.Step-1: Make sure that
package.json
contains @angular/animations
in dependencies block. If not available then either upgrade Angular CLI or configure @angular/animations
in dependencies block and run npm install .
Step-2: Configure
BrowserAnimationsModule
in application module to support animations.
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ imports: [ --- BrowserAnimationsModule ] --- }) export class AppModule { }
on-off.animation.ts
import { animate, state, style, transition, trigger } from '@angular/animations'; export const ON_OFF_ANIMATION = trigger('onOffTrigger', [ state('off', style({ backgroundColor: '#E5E7E9', transform: 'scale(1)' })), state('on', style({ backgroundColor: '#17202A', transform: 'scale(1.1)' })), transition('off => on', animate('.6s 100ms ease-in')), transition('on => off', animate('.7s 100ms ease-out')) ]);
onOffTrigger
is trigger name.
Step-4: To use animation in component, the decorator
@Component
provides a metadata named as animations
.
import { Component } from '@angular/core'; import { ON_OFF_ANIMATION } from './animations/on-off.animation'; @Component({ --- animations: [ ON_OFF_ANIMATION ] }) export class BookComponent {}
animations
metadata we can write animation code inline or provide the constant that is assigned with animation code. Inline animation code within component can be written as follows.
import { Component } from '@angular/core'; @Component({ --- animations: [ trigger('onOffTrigger', [ state('off', style({ backgroundColor: '#E5E7E9', transform: 'scale(1)' })), state('on', style({ backgroundColor: '#17202A', transform: 'scale(1.1)' })), transition('off => on', animate('.6s 100ms ease-in')), transition('on => off', animate('.7s 100ms ease-out')) ])] }) export class BookComponent {}
onOffTrigger
is trigger name.
Step-5: To use animation in our HTML template we need to bind trigger name using property binding. Suppose we have an animation trigger with name
onOffTrigger
then it will be bound to HTML element using @
as [@onOffTrigger] = "trigger_state_name"
.
<div [@onOffTrigger] = "trigger_state_name "> --- </div>
off
and on
that will be assigned to [@onOffTrigger]
at run time.
Create Service and Component for Demo
Find a service and component that we will use in our demo.book.service.ts
import { Injectable } from '@angular/core'; import { Book } from './book'; const BOOKS: Book[] = [ {"id": 1, "name": "Java", "author": "Mahesh", "state": "off"}, {"id": 2, "name": "Angular", "author": "Mahesh", "state": "off"}, {"id": 3, "name": "Spring", "author": "Krishna", "state": "off"}, {"id": 4, "name": "Hibernate", "author": "Krishna", "state": "off"} ]; let booksPromise = Promise.resolve(BOOKS); @Injectable() export class BookService { getBooks(): Promise<Book[]> { return booksPromise; } addBook(book: Book): Promise<Book> { return this.getBooks() .then(books => { let maxIndex = books.length - 1; let bookWithMaxIndex = books[maxIndex]; book.id = bookWithMaxIndex.id + 1; book.state= 'off'; books.push(book); return book; } ); } }
export interface Book { id: number; name: string; author: string; state: string; }
import { Component, OnInit } from '@angular/core'; import { BookService } from './book.service'; import { Book } from './book'; import { ON_OFF_1_ANIMATION } from './animations/on-off-1.animation'; import { ON_OFF_2_ANIMATION } from './animations/on-off-2.animation'; import { ON_OFF_3_ANIMATION } from './animations/on-off-3.animation'; import { ON_OFF_4_ANIMATION } from './animations/on-off-4.animation'; @Component({ templateUrl: 'book.component.html', animations: [ ON_OFF_1_ANIMATION, ON_OFF_2_ANIMATION, ON_OFF_3_ANIMATION, ON_OFF_4_ANIMATION, ] }) export class BookComponent implements OnInit { books = {} as Promise<Book[]>; constructor(private bookService: BookService) { } ngOnInit() { this.books = this.bookService.getBooks(); } toggle(book: Book) { book.state = (book.state === 'on') ? 'off' : 'on'; } }
<h3>Click and then Click to test Animation</h3> <ul [ngClass]= "'sub-menu'"> <li *ngFor="let book of books | async" [@onOff1Trigger] = "book.state" (click)="toggle(book)"> <a>{{book.name}}</a> </li> </ul> <br/> <ul [ngClass]= "'sub-menu'"> <li *ngFor="let book of books | async" [@onOff2Trigger] = "book.state" (click)="toggle(book)"> <a>{{book.name}}</a> </li> </ul> <br/> <ul [ngClass]= "'sub-menu'"> <li *ngFor="let book of books | async" [@onOff3Trigger] = "book.state" (click)="toggle(book)"> <a>{{book.name}}</a> </li> </ul> <br/> <ul [ngClass]= "'sub-menu'"> <li *ngFor="let book of books | async" [@onOff4Trigger] = "book.state" (click)="toggle(book)"> <a>{{book.name}}</a> </li> </ul>

trigger
trigger
is an animation-specific function that creates a trigger with state
and transition
entries. trigger
function accepts following arguments.
1. Trigger name
2. Array of
state
and transition
.
Trigger is used as follows.
trigger("onOffTrigger", [ state(...), state(...), transition(...), transition(...) ])
state
and transition
entries.
style
style
is an animation-specific function. It is defined with key/value of CSS properties. style
function is passed as an argument in animation-specific functions such as state
, transition
, animate
and keyframes
. Animation style
function is defined as follows.
style({ backgroundColor: '#E5E7E9', color: '#1C2833', fontSize: '18px', transform: 'scale(1)' })
state
state
is an animation-specific function. It is an animation state within the given trigger
. state
function accepts following arguments.
1. State name
2.
style
Find the example.
on-off-1.animation.ts
import { animate, state, style, transition, trigger } from '@angular/animations'; export const ON_OFF_1_ANIMATION = trigger('onOff1Trigger', [ state('off', style({ backgroundColor: '#E5E7E9', color: '#1C2833', fontSize: '18px', transform: 'scale(1)' })), state('on', style({ backgroundColor: '#17202A', color: '#F0F3F4', fontSize: '22px', transform: 'scale(1.1)' })) ]);
onOff1Trigger
in our HTML template.
<ul [ngClass]= "'sub-menu'"> <li *ngFor="let book of books | async" [@onOff1Trigger] = "book.state" (click)="toggle(book)"> <a>{{book.name}}</a> </li> </ul>
book.state
value is off
then the animation state
with name off
will be applied and when the book.state
value is on
then the animation state
with name on
will be applied.
State can also be void and * in animation.
void : This state is reserved by Angular. void state means element is not the part of application anymore. void state example is that when
ngIf
expression value is false
and that element is no more in DOM.
* : This is the default state. This is a state which has not been declared within the
trigger
function. * state is used for dynamic start and ending state in animation.
animate
animate
is an animation-specific function. It specifies an animation step. We need to pass following arguments to animate
function.
1. Timing expression
2.
style
or keyframes
function. This argument is optional.
Timing expression is the combination of duration, delay and easing. They are written in following formats.
Timing expression: 'duration delay easing'
Find the explanation.
duration: It defines how long animation will take place. It can be a plane number or string. If we write plane number then by default the time unit will be milliseconds. If we write 100, it means 100 milliseconds and if we want to specify time unit then write as string. '100ms' means 100 milliseconds and '0.1s' means 0.1 second.
delay: This is the time gap between animation trigger and beginning of transition. It is written in string with time unit in string.
easing: It defines how the animations accelerates and decelerates during its runtime. Easing can be ease, ease-in, ease-out, ease-in-out etc.
Find the examples of
animate
with timing expression.
1.
animate(100)
Animation will take place for 100ms just after animation trigger.
2.
animate( '0.6s 100ms ease-in')
delay: 100ms
easing: ease-in
After animation trigger there will be a delay of 100 milliseconds to start animation and then animation will take place for 0.6 seconds with ease-in function.
3.
animate('0.7s ease-out')
easing: ease-out
Animation will start just after trigger. Animation will take place for 0.7 seconds with ease-out function.
Find the example of
animate
with time expression and style
.
animate('0.6s 100ms ease-in', style({ fontSize: '19px', backgroundColor: 'blue' }))
style
will be active from animation start to animation end.
transition
transition
function is an animation-specific function. transition
function runs the steps of animation for the given state change expression. State change expression is written as state1 => state2
or state2 => state1
or state1 <=> state2
. transition
function associates state change expression with animation steps. Find the arguments of transition
function.
1. State change expression such as (state1 => state2)
2. Animation step or array of animation steps.
Find some
transition
function example.
1.
transition('state1 => state2', animate(...)) transition('state2 => state3', animate(...)) transition('state3 => state1', animate(...))
transition
function, animation will take place for the defined state change expression.
2. If for two states
animation(...)
definition is same then we can write transition
function as follows.
transition('state1 <=> state2', animate(...))
animation(...)
definition is same then state change expression will be written comma separated.
transition('state1 => state2, state2 => state3', animate(...))
transition('* => *', animate(...))
5.
transition('void => *', animate(...))
void => *
is :enter
and so above transition can also be written as following.
transition(':enter', animate(...))
transition('* => void', animate(...))
* => void
is :leave
and so above transition can also be written as following.
transition(':leave', animate(...))
Example-1: Find the example of
transition
. Here animate
is using only time expression.
on-off-2.animation.ts
import { animate, state, style, transition, trigger } from '@angular/animations'; export const ON_OFF_2_ANIMATION = trigger('onOff2Trigger', [ state('off', style({ backgroundColor: '#E5E7E9', color: '#1C2833', fontSize: '18px', transform: 'scale(1)' })), state('on', style({ backgroundColor: '#17202A', color: '#F0F3F4', fontSize: '22px', transform: 'scale(1.1)' })), transition('off => on', animate('0.6s 100ms ease-in')), transition('on => off', animate('0.7s 100ms ease-out')) ]);
onOff2Trigger
.
<ul [ngClass]= "'sub-menu'"> <li *ngFor="let book of books | async" [@onOff2Trigger] = "book.state" (click)="toggle(book)"> <a>{{book.name}}</a> </li> </ul>
transition
. Here animate
is using time expression and style
.
on-off-3.animation.ts
import { animate, state, style, transition, trigger } from '@angular/animations'; export const ON_OFF_3_ANIMATION = trigger('onOff3Trigger', [ state('off', style({ backgroundColor: '#E5E7E9', color: '#1C2833', fontSize: '18px', transform: 'scale(1)' })), state('on', style({ backgroundColor: '#17202A', color: '#F0F3F4', fontSize: '22px', transform: 'scale(1.1)' })), transition('off => on', animate('0.6s 100ms ease-in', style({fontSize: '19px', backgroundColor: 'blue' }))), transition('on => off', animate('0.7s 100ms ease-out', style({fontSize: '19px', backgroundColor: 'red'}))) ]);
onOff3Trigger
.
<ul [ngClass]= "'sub-menu'"> <li *ngFor="let book of books | async" [@onOff3Trigger] = "book.state" (click)="toggle(book)"> <a>{{book.name}}</a> </li> </ul>
keyframes
keyframes
is an animation-specific function that is used with animate
function. keyframes
applies different style at different offset of duration of animation. Find the code snippet.
animate('0.6s 100ms ease-in',keyframes([ style({fontSize: '19px', backgroundColor: 'yellow', offset: 0.1 }), style({fontSize: '20px', backgroundColor: 'green', offset: 0.3 }), style({fontSize: '21px', backgroundColor: 'red', offset: 0.5 }) ]))
style
within a keyframes
using offset. Here we have set more than one style that will change according to their offset within the animation start to end. If we do not use offset then it will automatically be calculated. Find the example.
on-off-4.animation.ts
import { animate, state, style, transition, trigger, keyframes } from '@angular/animations'; export const ON_OFF_4_ANIMATION = trigger('onOff4Trigger', [ state('off', style({ backgroundColor: '#E5E7E9', color: '#1C2833', fontSize: '18px', transform: 'scale(1)' })), state('on', style({ backgroundColor: '#17202A', color: '#F0F3F4', fontSize: '22px', transform: 'scale(1.1)' })), transition('off => on', animate('0.6s 100ms ease-in',keyframes([ style({fontSize: '19px', backgroundColor: 'yellow', offset: 0.1 }), style({fontSize: '20px', backgroundColor: 'green', offset: 0.3 }), style({fontSize: '21px', backgroundColor: 'red', offset: 0.5 }) ]))), transition('on => off', animate('0.7s 100ms ease-out', keyframes([ style({fontSize: '22px', backgroundColor: 'yellow', offset: 0 }), style({fontSize: '21px', backgroundColor: 'green', offset: 0.2 }), style({fontSize: '20px', backgroundColor: 'red', offset: 0.4 }), style({fontSize: '19px', backgroundColor: 'blue', offset: 0.5 }) ]))) ]);
onOff4Trigger
will be used as follows.
<ul [ngClass]= "'sub-menu'"> <li *ngFor="let book of books | async" [@onOff4Trigger] = "book.state" (click)="toggle(book)"> <a>{{book.name}}</a> </li> </ul>
sequence
sequence
is an animation-specific function. It is used within a transition
or group
function. sequence
function will contain the array of style
and animate
functions. They will execute in sequence. Find the code snippet.
transition('* => void', sequence([ style({backgroundColor: '#0D6063'}), animate('0.6s ease-out', style({transform: 'rotate(-270deg)', opacity: 0})) ]))
sequence
is not necessary. It is default, we can directly use array of style
and animate
functions.
transition('* => void', [ style({backgroundColor: '#0D6063'}), animate('0.6s ease-out', style({transform: 'rotate(-270deg)', opacity: 0})) ])
group
group
is an animation-specific function that can be used within a transition
or sequence
function. group
contains the entries of animations steps that run in parallel.
transition('void => *', [ style({ backgroundColor: '#E3E8EC', transform: 'translateX(300%)', opacity: 0 }), group([ animate('0.5s 0.1s ease-in', style({ transform: 'translateX(0)', })), animate('0.3s 0.1s ease', style({ opacity: 1 })) ]) ])
transition
is using state change expression and sequence. Within the sequence we are using style
and group
and group
is using the entries of animate
functions. These animate
functions will run in parallel for the given durations.
(void => *) alias (:enter) and (* => void) alias (:leave)
Here we will provide examples of void => *
and * => void
state change expression. void => *
has the alias :enter
and * => void
has alias :leave
. void
state means a state for the element when element is not available in DOM. *
is the default state. This is a state which has not been declared within the trigger
function. * state is used for dynamic start and ending state in animation. Now find the examples.
Example-1: Using (void => *) and (* => void)
round-anticlock.animation.ts
import { animate, state, style, transition, trigger, sequence } from '@angular/animations'; export const ROUND_ANTICLOCK_ANIMATION = trigger('roundAntiClockTrigger', [ state('in', style({ backgroundColor: '#E5E7E9', color: '#1B2172' })), transition('void => *', sequence([ style({ transform: 'rotate(270deg)', opacity: 0, backgroundColor: '#0D6063' }), animate('0.6s ease-in-out') ])), transition('* => void', sequence([ style({backgroundColor: '#0D6063'}), animate('0.6s ease-out', style({transform: 'rotate(-270deg)', opacity: 0})) ])) ]);
style
is using transform
CSS property. It applies 2D or 3D transformation to an element. The value of transform
can be translate, rotate, scale, move, skew, etc.
addbook.component.ts
import { Component, HostBinding } from '@angular/core'; import { Router } from '@angular/router'; import { BookService } from './book.service'; import { Book } from './book'; import { ROUND_ANTICLOCK_ANIMATION } from './animations/round-anticlock.animation'; @Component({ templateUrl: './addbook.component.html', styles: [ ':host { position: absolute; top: 20%; left: 5%; border: 3px solid black; }' ], animations: [ ROUND_ANTICLOCK_ANIMATION ] }) export class AddBookComponent { @HostBinding('@roundAntiClockTrigger') roundAntiClockTrigger = 'in'; book = {} as Book; constructor(private bookService: BookService, private router: Router) { } add() { this.bookService.addBook(this.book).then( () => this.router.navigate(['/book']) ); } }
HostBinding
. We need to pass the trigger name to HostBinding
.
@HostBinding('@roundAntiClockTrigger') roundAntiClockTrigger = 'in';
'in'
is the initial state name of animation defined in animation trigger function. HostBinding
can also bind CSS property to host element such as
@HostBinding('style.display') display = 'block'; @HostBinding('style.position') position = 'absolute';
:host
as given below.
:host { position: absolute; top: 20%; left: 5%; border: 3px solid black; }
Angular Component Styles :host, :host-context, /deep/ Selector Example
Now find the html template.
addbook.component.html
<h3>Add Book</h3> <p>Enter Name: <input [(ngModel)]="book.name"> </p> <p>Enter Author: <input [(ngModel)]="book.author"> </p> <p> <button type="button" (click)="add()">Add</button> </p>
We have already discussed that
:enter
is the alias of void => *
state change expression and :leave
is the alias of * => void
state change expression. Now find the example.
fly-in-out.animation.ts
import { animate, state, style, transition, trigger, group } from '@angular/animations'; export const FLY_IN_OUT_ANIMATION = trigger('flyInOutTrigger', [ state('in', style({ backgroundColor: '#7BBEFC', color: '#080809', transform: 'translateX(0)', opacity: 1 })), transition(':enter', [ style({ backgroundColor: '#E3E8EC', transform: 'translateX(300%)', opacity: 0 }), group([ animate('0.5s 0.1s ease-in', style({ transform: 'translateX(0)', })), animate('0.3s 0.1s ease', style({ opacity: 1 })) ]) ]), transition(':leave', [ style({ backgroundColor: '#9DCEFC', }), group([ animate('0.5s ease-out', style({ transform: 'translateX(300%)' })), animate('0.3s 0.1s ease', style({ opacity: 0 })) ]) ]) ]);
import { Component, OnInit, HostBinding } from '@angular/core'; import { FLY_IN_OUT_ANIMATION } from './animations/fly-in-out.animation'; import { BookService } from './book.service'; import { Book } from './book'; @Component({ templateUrl: './book-detail.component.html', styles: [ ':host { position: absolute; top: 20%; left: 5%; border: 3px solid black; }' ], animations: [ FLY_IN_OUT_ANIMATION ] }) export class BookDetailComponent implements OnInit { @HostBinding('@flyInOutTrigger') flyInOutTrigger = 'in'; books = = {} as Promise<Book[]>; constructor(private bookService: BookService) { } ngOnInit() { this.books = this.bookService.getBooks(); } }
<h3>Book Details</h3> <p *ngFor="let book of books | async"> <b>Id:</b> {{book.id}}, <b>Name:</b> {{book.name}}, <b>Author:</b> {{book.author}} </p>

Application Component and Module used in Demo
app.component.tsimport { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <nav [ngClass] = "'parent-menu'"> <ul> <li><a routerLink="/book" routerLinkActive="active">Book</a></li> <li><a routerLink="/add-book" routerLinkActive="active">Add Book</a></li> <li><a routerLink="/book-detail" routerLinkActive="active">Book Details</a></li> </ul> </nav> <router-outlet></router-outlet> ` }) export class AppComponent { }
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { BookComponent } from './book.component'; import { AddBookComponent } from './addbook.component'; import { BookDetailComponent } from './book-detail.component'; const routes: Routes = [ { path: 'book', component: BookComponent, }, { path: 'add-book', component: AddBookComponent }, { path: 'book-detail', component: BookDetailComponent }, { path: '', redirectTo: '/book', pathMatch: 'full' } ]; @NgModule({ imports: [ RouterModule.forRoot(routes) ], exports: [ RouterModule ] }) export class AppRoutingModule{ }
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { AppComponent } from './app.component'; import { BookComponent } from './book.component'; import { AddBookComponent } from './addbook.component'; import { BookDetailComponent } from './book-detail.component'; import { BookService } from './book.service'; import { AppRoutingModule } from './app-routing.module'; @NgModule({ imports: [ BrowserModule, FormsModule, AppRoutingModule, BrowserAnimationsModule ], declarations: [ AppComponent, BookComponent, AddBookComponent, BookDetailComponent ], providers: [ BookService ], bootstrap: [ AppComponent ] }) export class AppModule { }
.parent-menu ul { list-style-type: none; margin: 0; padding: 0; overflow: hidden; background-color: #333; } .parent-menu li { float: left; } .parent-menu li a { display: block; color: white; text-align: center; padding: 15px 15px; text-decoration: none; } .parent-menu li a:hover:not(.active) { background-color: #111; } .parent-menu .active{ background-color: #4CAF50; } .sub-menu ul { list-style-type: none; padding: 0; } .sub-menu li { display: inline-block; width: 120px; line-height: 50px; padding: 0 10px; box-sizing: border-box; background-color: #eee; border-radius: 4px; margin: 10px; cursor: pointer; overflow: hidden; white-space: nowrap; }
Run Application
To run the application, find the following steps.1. Download source code using download link given below on this page.
2. Use downloaded src in your Angular CLI application. To install Angular CLI, find the link.
3. Run ng serve using command prompt.
4. Now access the URL http://localhost:4200
Find the print screen.
References
Introduction to Angular animationsAnimations API