skills/dev-skills/angular-developer/references/angular-animations.md
When animating elements in Angular, first analyze the project's Angular version in package.json.
For modern applications (Angular v20.2 and above), prefer using native CSS with animate.enter and animate.leave. For older applications, you may need to use the deprecated @angular/animations package.
Modern Angular provides animate.enter and animate.leave to animate elements as they enter or leave the DOM. They apply CSS classes at the appropriate times.
animate.enter and animate.leaveUse these directly on elements to apply CSS classes during the enter or leave phase. Angular automatically removes the enter classes when the animation completes. For animate.leave, Angular waits for the animation to finish before removing the element from the DOM.
animate.enter example:
@if (isShown()) {
<div class="enter-container" animate.enter="enter-animation">
<p>The box is entering.</p>
</div>
}
/* Ensure you have a starting style if using transitions instead of keyframes */
.enter-container {
border: 1px solid #dddddd;
margin-top: 1em;
padding: 20px;
font-weight: bold;
font-size: 20px;
}
.enter-container p {
margin: 0;
}
.enter-animation {
animation: slide-fade 1s;
}
@keyframes slide-fade {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
Note: animate.leave may be added to child elements being removed.
You can bind to (animate.enter) and (animate.leave) to call functions or use JS libraries like GSAP.
@if(show()) {
<div (animate.leave)="onLeave($event)">...</div>
}
import { AnimationCallbackEvent } from '@angular/core';
onLeave(event: AnimationCallbackEvent) {
// Custom animation logic here
// CRITICAL: You MUST call animationComplete() when done so Angular removes the element!
event.animationComplete();
}
CSS offers robust tools for advanced animation sequences.
Toggle CSS classes on elements using property binding to trigger transitions.
<div [class.open]="isOpen">...</div>
div {
transition: height 0.3s ease-out;
height: 100px;
}
div.open {
height: 200px;
}
You can use css-grid to animate to auto height.
.container {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.3s;
}
.container.open {
grid-template-rows: 1fr;
}
.container > div {
overflow: hidden;
}
animation-delay or transition-delay with different values for items in a list.animation shorthand (e.g., animation: rotate 3s, fade-in 2s;).Retrieve animations directly using standard Web APIs:
const animations = element.getAnimations();
animations.forEach((anim) => anim.pause());
For older projects (pre v20.2 or where @angular/animations is already heavily used), you use the component metadata DSL.
Important: Do not mix legacy animations and animate.enter/leave in the same component.
bootstrapApplication(App, {
providers: [provideAnimationsAsync()],
});
import {signal} from '@angular/core';
import {trigger, state, style, animate, transition} from '@angular/animations';
@Component({
animations: [
trigger('openClose', [
state('open', style({opacity: 1})),
state('closed', style({opacity: 0})),
transition('open <=> closed', [animate('0.5s')]),
]),
],
template: `<div [@openClose]="isOpen() ? 'open' : 'closed'">...</div>`,
})
export class OpenClose {
isOpen = signal(true);
}