The @angular/animations package is deprecated as of v20.2, which also introduced the new animate.enter and animate.leave feature to add animations to your application. Using these new features, you can replace all animations based on @angular/animations with plain CSS or JS animation libraries. Removing @angular/animations from your application can significantly reduce the size of your JavaScript bundle. Native CSS animations generally offer superior performance, as they can benefit from hardware acceleration. This guide walks through the process of refactoring your code from @angular/animations to native CSS animations.
Just like with the animations package, you can create reusable animations that can be shared across your application. The animations package version of this had you using the animation() function in a shared typescript file. The native CSS version of this is similar, but lives in a shared CSS file.
The animations package allowed you to define various states using the state() function within a component. Examples might be an open or closed state containing the styles for each respective state within the definition. For example:
.open { height: '200px'; opacity: 1; background-color: 'yellow';transition: all 1s;}.closed { height: '100px'; opacity: 0.8; background-color: 'blue';transition: all 1s;}
Triggering the open or closed state is done by toggling classes on the element in your component. You can find examples of how to do this in our template guide.
The animations package animate() function allows for providing timing, like duration, delays and easing. This can be done natively with CSS using several css properties or shorthand properties.
Specify animation-duration, animation-delay, and animation-timing-function for a keyframe animation in CSS, or alternatively use the animation shorthand property.
Similarly, you can use transition-duration, transition-delay, and transition-timing-function and the transition shorthand for animations that are not using @keyframes.
The animations package required specifying triggers using the trigger() function and nesting all of your states within it. With native CSS, this is unnecessary. Animations can be triggered by toggling CSS styles or classes. Once a class is present on an element, the animation will occur. Removing the class will revert the element back to whatever CSS is defined for that element. This results in significantly less code to do the same animation. Here's an example:
The animations package offers the ability to match your defined states to a transition via strings. For example, animating from open to closed would be open => closed. You can use wildcards to match any state to a target state, like * => closed and the void keyword can be used for entering and exiting states. For example: * => void for when an element leaves a view or void => * for when the element enters a view.
These state matching patterns are not needed at all when animating with CSS directly. You can manage what transitions and @keyframes animations apply based on whatever classes you set and / or styles you set on the elements. You can also add @starting-style to control how the element looks upon immediately entering the DOM.
The animations package offers the ability to animate things that have been historically difficult to animate, like animating a set height to height: auto. You can now do this with pure CSS as well.
The animations package offered the previously mentioned pattern matching for entering and leaving but also included the shorthand aliases of :enter and :leave.
Along with the aforementioned :enter and :leave, there's also :increment and :decrement. You can animate these also by adding and removing classes. Unlike the animation package built-in aliases, there is no automatic application of classes when the values go up or down. You can apply the appropriate classes programmatically. Here's an example:
Unlike the animations package, when multiple animations are specified within a given component, no animation has priority over another and nothing blocks any animation from firing. Any sequencing of animations would have to be handled by your definition of your CSS animation, using animation / transition delay, and / or using animationend or transitionend to handle adding the next css to be animated.
Applying this class to an element prevents any animation from firing on that element. You could alternatively scope this to your entire DOM or section of your DOM to enforce this behavior. However, this prevents animation events from firing. If you are awaiting animation events for element removal, this solution won't work. A workaround is to set durations to 1 millisecond instead.
Use the prefers-reduced-motion media query to ensure no animations play for users that prefer less animation.
The animations package exposed callbacks for you to use in the case that you want to do something when the animation has finished. Native CSS animations also have these callbacks.
The Web Animations API has a lot of additional functionality. Take a look at the documentation to see all the available animation APIs.
NOTE: Be aware of bubbling issues with these callbacks. If you are animating children and parents, the events bubble up from children to parents. Consider stopping propagation or looking at more details within the event to determine if you're responding to the desired event target rather than an event bubbling up from a child node. You can examine the animationname property or the properties being transitioned to verify you have the right nodes.
The animations package has built-in functionality for creating complex sequences. These sequences are all entirely possible without the animations package.
In the animations package, you could target specific elements by using the query() function to find specific elements by a CSS class name, similar to document.querySelector(). This is unnecessary in a native CSS animation world. Instead, you can use your CSS selectors to target sub-classes and apply any desired transform or animation.
To toggle classes for child nodes within a template, you can use class and style bindings to add the animations at the right points.
The stagger() function allowed you to delay the animation of each item in a list of items by a specified time to create a cascade effect. You can replicate this behavior in native CSS by utilizing animation-delay or transition-delay. Here is an example of what that CSS might look like.
The animations package has a group() function to play multiple animations at the same time. In CSS, you have full control over animation timing. If you have multiple animations defined, you can apply all of them at once.
Items reordering in a list works out of the box using the previously described techniques. No additional special work is required. Items in a @for loop will be removed and re-added properly, which will fire off animations using @starting-styles for entry animations. Alternatively, you can use animate.enter for this same behavior. Use animate.leave to animate elements as they are removed, as seen in the example above.
The AnimationPlayer class allows access to an animation to do more advanced things like pause, play, restart, and finish an animation through code. All of these things can be handled natively as well.
You can retrieve animations off an element directly using Element.getAnimations(). This returns an array of every Animation on that element. You can use the Animation API to do much more than you could with what the AnimationPlayer from the animations package offered. From here you can cancel(), play(), pause(), reverse() and much more. This native API should provide everything you need to control your animations.