Animations breathe life into your application and can significantly boost the overall user experience for your users. While animation is a broad and sometimes daunting subject, bringing it into your Angular projects doesn't need to be complicated. I’ll walk you through 3 straightforward approaches to animating your apps, plus some extra resources to simplify the journey even further.
This post serves as a brief overview of Angular animations. For deeper material, have a look at my Indepth Guide to Animation in Angular on indepth.dev or my Angular Animation Explorer project. These cover advanced scenarios, touching on performance, debugging, and other relevant aspects.
CSS Keyframes and Transitions
Because Angular operates in browsers with HTML and CSS at its core, you can apply CSS animations in your Angular app just as you would in any standard, non-Angular web project. The animation is set up in your stylesheet—either using a transition or keyframes—and it fires when the class holding that animation is applied.
To create a growth effect with the transition property, your code might resemble this:
#targetElement {
transition: tranform 0.5s;
}
#targetElement.expand {
transform: scale(1.1);
}
When an animation involves just a start and end state, CSS
transitionis the perfect fit.
Inside the template, we attach the expand class to a property, which toggles the class to fire off our defined animation. A boolean shouldExpand can be introduced and flipped to true to start the effect. With Angular's class binding, we assign it to the variable as follows:
<div #targetElement [class.expand]="shouldExpand"></div>
CSS keyframes animation, conversely, offers finer-grained control over our animation, allowing us to specify what occurs at every keyframe along the way. This proves perfect for crafting more intricate animations that rely on intermediate stages within the sequence and that entail some form of repetition, whether finite or infinite.
We can take the same expand animation illustration and convert it from a transition-based approach to one driven by keyframes:
#targetElement.expand {
animation: expand 0.5s;
}
@keyframes expand {
0% {
transform: scale(1);
}
100% {
transform: scale(1.1);
}
}
After that, the expand class can be bound to a variable, letting us control the animation's activation based on a condition:
<div #targetElement [class.expand]="shouldExpand"></div>
Transition and keyframe animations both expose events we can tap into. Depending on the type chosen,
animationendhandles keyframe animations whiletransitionendlistens for CSS transition completion.
Working this way brings a clear benefit: any CSS animation library based on toggling classes becomes immediately usable. Among the well-known options in this category are animate.css and magic.css. For a broader list, Chris Coyier wrote an excellent article over at CSS Tricks.
Web Animation APIs
WAAPI, short for Web Animation APIs, bridges the gap between declarative CSS animation techniques and dynamic JavaScript-driven motion. As of the writing of this piece, browser support includes Firefox 48+ and Chrome 36+. A solid and feature-complete polyfill also exists, which makes production adoption a safe bet today.
Anyone who has worked with WAAPI in a JavaScript project will find this section quite recognizable. In vanilla JavaScript, grabbing a DOM element typically means assigning it an id and then calling document.getElement.byId with that id to obtain a reference. Angular offers a different route: using a template reference variable (#) combined with the ViewChild decorator to achieve the same outcome.
The initial step here is to set up the div we intend to animate and assign it a reference variable called targetElement:
<div #targeElement></div>
You can grab this element with the ViewChild decorator, supplying the reference variable tied to it (#targetElement):
import { ViewChild, ElementRef } from '@angular/core';
@ViewChild('targetElement') targetElement: ElementRef;
To bring this element to life, invoke animate on its nativeElement property, supplying both the animation definition array and the timing configuration:
startAnimation(): void {
this.targetElement.nativeElement.animate(this.getShakeAnimation(), this.getShakeAnimationTiming());
}
getShakeAnimation() {
return [
{ transform: 'rotate(0)' },
{ transform: 'rotate(2deg)' },
{ transform: 'rotate(-2deg)' },
{ transform: 'rotate(0)' },
];
}
getShakeAnimationTiming() {
return {
duration: 300,
iterations: 3,
};
}
WAAPI provides additional utility methods and properties that integrate into an Angular app just like in a standard vanilla setup. This includes controls for pausing, canceling, and reversing ongoing animations, alongside event callbacks like oncancel and onfinish. Additional API details are available in MDN Web Docs.
Angular Animations
The @angular/animations module is a feature-rich package bundled with Angular, offering a DSL (domain-specific language) to describe animation sequences as a series of CSS-style transformations over a duration. Its implementation relies on the native Web Animations API, but degrades gracefully to CSS keyframes whenever the user's environment lacks support for WAAPI.
This animation system is modeled after CSS transitions, so any property capable of being styled or transformed through plain CSS is equally flexible within Angular animations. As a result, the animations benefit from performance characteristics similar to CSS that align smoothly with Angular's architecture.
Animations driven through Angular's BrowserAnimationModule cycle through four distinct phases. You can view these as a set of guiding questions—why, what, where, and how—each response dictating the resulting behavior:
- Evaluate data binding expression - pinpoints the animation state currently assigned to the host element (why)
- Data binding target - identifies the specific target that supplies the CSS styles for the affected element's state (what)
- State - specifies the exact CSS styles for the element at that particular time (where)
- Transition - defines the process for applying those styles during a state shift (how)
Adding @angular/animations to your project requires importing BrowserAnimationsModule and placing it into the module's imports array:
import { NgModule } from "@angular/core";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
@NgModule({
imports: [BrowserAnimationsModule],
})
export class AppModule {}
Angular Animations support many scenarios, and common usage in my projects includes transitions for elements appearing and disappearing, adjustments to component states, and cascaded sequences. I’ll illustrate a straightforward enter/leave animation with an example.
Start by defining the animations, then register them in the animations array within the component decorator:
import { trigger, transition, style, animate } from '@angular/animations';
@Component({
...
animations: [
trigger('fadeSlideInOut', [
transition(':enter', [
style({ opacity: 0, transform: 'translateY(10px)' }),
animate('500ms', style({ opacity: 1, transform: 'translateY(0)' })),
]),
transition(':leave', [
animate('500ms', style({ opacity: 0, transform: 'translateY(10px)' })),
]),
])
],
})
To apply the animation when an element enters (:enter block) or exits (:leave block) the DOM, we reference the trigger name — fadeSlideInOut in this case — in our template by prefixing it with @.
<div *ngIf="show" @fadeSlideInOut>...</div>
For a deeper dive into Angular Animations, consult the official documentation, or explore the beginner and advanced sections of the Angular Animations Explorer.
Conclusion
That wraps up this article. I hope this brief overview of animations in Angular was useful. To dig deeper into any of the approaches covered, browse this reference, which offers live demonstrations for each method and beyond. For similar content or questions, drop a comment below or reach out on Twitter at @williamjuan27.
