Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

Authors: @thePunderWoman
Area: Angular Framework
Posted: June 23, 2025
Status: Closed

The Angular team created @angular/animations over eight years ago. That was before the native CSS platform had all the native CSS animation features that are built in today, like transform and @keyframes. At the time, @angular/animations offered innovative and important features to bring immersive and beautiful user experiences to your applications. However, so much has changed with the web platform, and the package is now showing its age. This RFC explores our intent to deprecate @angular/animations with its eventual end-of-life, while also exploring a replacement that modernizes how we do animations in Angular.

Over the years, a few problems have emerged with @angular/animations. The JavaScript size impact of the package is significant, coming in around 60kb. Animations built using @angular/animations are run in JavaScript and cannot take advantage of hardware acceleration. The @angular/animations API only applies to Angular and does not translate to any skill outside of the Angular ecosystem. Also other widely-used third-party animation libraries have sprung up and become very popular, which are more difficult to use in Angular.

We'd like to add two new native features to Angular: animate.in and animate.out. Angular works well with pure CSS animations, but there are a few rough edges that we believe these options will solve. We've created a brand new migration guide that outlines how to migrate from @angular/animations to using pure CSS animations. This guide covers everything needed to migrate, but there are a few rough edges. Animating removal of elements is the most notable. By providing these new options, we can automatically handle the delayed removal for you and let you get back to creating apps your users will love.

What kind of feedback are we looking for?

While we're excited to hear any and all comments on the new animation options in Angular, we have additionally called out specific discussion points throughout the RFC for directed feedback. When you leave a comment, be sure to note the open question(s) to which you're responding.

As always, keep our code of conduct in mind. We know that a proposal of this scope significantly impacts Angular and the way you use it in your projects. We appreciate your commitment and investment in this project and ask to keep comments respectful.

Goals

  • Provide an ergonomic and straightforward API for adding animations to components and / or elements
  • Remove the need for adding a dependency on the animations package
  • Provide the ability to use third party animation libraries

API

Let's talk about the new API and how it will function.

animate.out

Animating elements away from the DOM as they are being removed is a bit tricky to manage manually as there is no @starting-styles equivalent natively. The animate.out feature delays removal of an element from the DOM until the associated animation completes.

The animate.out feature will accept three different types with two different usage patterns. The first pattern is providing a string or string array. This string is the class or classes that contains the animations you'd like to apply as the element is removed. The second pattern is binding to an event with a custom function. The function option is bound to an event that is raised when the element leaves the view. This would allow use of third party animation libraries, like Anime.js or GSAP.

Example usages

<example-cmp animate.out="fancy-animation-class" />

<example-cmp [animate.out]="myDynamicCSSClasses" />

<other-example-cmp (animate.out)="animateFn($event)" />

Discussion Question 1: Should these options support setting styles directly like ngStyle bindings? (see example)

animate.in

The need for an animate.in feature is less important than an animate.out feature from a pure CSS perspective, as the CSS platform has added @starting-styles, which allows you to natively specify what animations and styles apply as an element enters the DOM. However, we'll also have a few more options, and for purely symmetrical reasons, we'll want to support the same signature.

The animate.in feature will accept three different value types with 2 different patterns, just like the animate.out feature offers. The first pattern is providing a string or string array. This string is the class or classes that contains the animations you'd like to apply as the element enters the view. The second pattern is binding to an event with a custom function. The function option is bound to an event that is raised when the element enters the view. Similarly to `animate.out`, this would allow use of third party animation libraries, like Anime.js or GSAP.

If you are just using CSS classes, you do not need to use the animate.in feature. However, animate.in automatically removes a specified CSS class after the animation finishes.

Example usages

<example-cmp animate.in="pretty-animation-class" />

<example-cmp [animate.in]="myDynamicCSSClasses" />

<other-example-cmp (animate.in)="animateFn($event)" />

Discussion Question 2: Is animate.in strictly necessary given the platform supports this behavior already?

Discussion Question 3: What is your preference on the naming? animate.in and animate.out? animate.enter and animate.leave? Something else?

Animation Function details and options

Both animate.in and animate.out also function as event bindings. This allows you to do whatever you would like to do for animation. The custom AnimationEvent will provide access to the element being animated and an animationComplete function. Note that animationComplete is unnecessary for animate.in, but will be required for the functionality of animate.out, as it involves element removal. This section is where we're looking for your feedback.

Option 1: Callback function

The native element reference allows you to call getAnimations or add more advanced animations with either native platform APIs or with third-party libraries. The animationComplete function needs to be called when the animation finishes to ensure that any behavior that's supposed to happen when the animation finishes, like element removal, happens. The animationComplete callback has a 4 second timeout, just like native view transitions. So if you forget to call the animationComplete function for out, an error will be thrown at 4 seconds. Here are two examples using third party animation libraries:

GSAP

animateFn = (event: AnimationEvent) => {
  gsap.to(event.element, {
     rotation: 360,
     duration: 5,
     ease: "elastic",
     onComplete() {
       event.animationComplete();
     }
  });
}

Anime.js

animateFn = (event: AnimationEvent) => {
  animate(event.element, {
    x: '16rem',
    delay: 500,
    loop: 2,
    alternate: true,
    onComplete: () => event.animationComplete()
  })
}

Option 2: ExtendableEvent

Another option is to rely on the ExtendableEvent api where we can rely on the event.waitUntil(promise) API. In this case, you would wrap your animation function in a promise that then gets used by waitUntil. If no promise is provided, the framework will assume no animation and immediately remove the element.

animateFn = (event: AnimationEvent) => {
  const animationPromise = new Promise((resolve,reject) => {
  animate(event.element, {
    x: '16rem',
    delay: 500,
    loop: 2,
    alternate: true,
    onComplete: () => resolve(),
  });
  });
  event.waitUntil(animationPromise);
}

Discussion Question 4: Which of these 2 options for using functions is the most ideal to you, and why? Do you have an alternative suggestion?

Discussion Question 5: What would you want out of testing tools for animations?

Future work

Scoped view transitions are currently being considered, which allows for a view transition on an element or DOM subtree. Once these have reached a supported state, we can add support for them, too.

Frequently Asked Questions

  1. Are these directives?
    No, they will be built natively into the framework to allow for better optimization and tree-shakability.

  2. Is there anywhere I can try this out?
    Yes. You can visit this stackblitz and play with our prototype. Note that the prototype does not support the animation function syntax yet.

  3. Can I get these animal style?
    You're thinking of a different in and out.

  4. What happens on the server?
    animate.in and animate.out will not execute on the server.

  5. How will tests work with animate.in and animate.out?
    We'll be providing a mechanism to disable animations in test environments. Functionally it would be the same as if all animations happened at 0 ms. The on complete functions are still called. So element removal still occurs.

  6. Can I use these as host bindings?
    Yes, we will make these host bindable.

You must be logged in to vote

Replies: 35 comments · 36 replies

Comment options

Amazing idea!

Q2: no

Q3: animate.out

You must be logged in to vote
0 replies
Comment options

Great Idea. Especially the Callbacks will be very useful in my opinion.

You must be logged in to vote
0 replies
Comment options

Wow 🤩, it would be great to use and implement all these powerful new CSS properties and get the full potential out of them. In my opinion, as I said earlier in the comments, the callback function will be the best feature proposed compared to what already exists (KIS 👍 ).

Q1 : Yes

Q2 : No, not really useful

Q3: No preferences as long as it's explicit

Q4: Callback function, 100% for simplicity and readability

Q5: To be able to debug / track problems with transitions or performance losses linked to animations in Angular Devtools( or to add direct compatibility with what Chrome already offers)

You must be logged in to vote
0 replies
Comment options

Q1: No, as it easily would lead to "too much logic in template", while not providing any additional use-cases.
Q2: Also, no, for the same reason. It will lead to things that should have be done with CSS-only, but now will use JS.
Q3: I slightly prefer enter and leave.
Q4: Option #1. The callback is simpler to grok. Also, it doesn't require creating additional synthetic events, and doesn't add the cognitive overhead of the promise constructor.
Q5: Get out of the way. In 98% of the cases I encountered, animations add visual clues, but don't make a difference for the app's logic. The 2% where it does make a difference should be watched in e2e more as in unit tests.

You must be logged in to vote
1 reply
@JelleBruisten
Comment options

Pretty much what I would have answered 👍

Comment options

I think these Animations would be very useful. Other frameworks require external libs for handling the animate-out for example. It would be really nice to have such features.

Q1: It's a good idea but I also would offer to style the animation in a Stylesheet by a custom CSS selector, since Angular is known to be better scalable in large codebase and separating HTML and CSS / SCSS is always a good idea.

Q2: To keep it consistent I would prefer animate.in. As a framework user I would expect to have the opposite of animate.out. Another reason for having an animate.in is to pass some handler function to animate.in. This behavior is not covered by CSS / SCSS and can be a new feature.

Q3: It's shorter to write animate.in or animate.out instead without having a tradeoff in understanding, so I would prefer these.

Q4: In this case Option 1 is more modern and doesn't require any creation or handling of Promises by offering the same features. It's API is clearer.

Q5: Testing an element with the new Vitest Support (or different Unit-, E2E-Frameworks) against before/after styling states can detect breaks in Styles. But instead, I would first focus on a clear animation API since testable animations on the presentational layer are a bit to overcomplicated by now.

You must be logged in to vote
0 replies
Comment options

Hey!

Just a point related to the FAQ / 3): I understand they are not directives... but my ng-brain is a bit confused by the syntax. 😅
I wonder: any explanation why we can't pretend they are directives?

Say, in a way changing the set of trade-offs:

<!-- I'd jump directly to the potential selectorless notation (just a draft) -->

<example-cmp animate.out="fancy-animation-class" />   <!-- IMHO this one is really off -->
<example-cmp @animate( out="fancy-animation-class" ) />

<example-cmp [animate.out]="myDynamicCSSClasses" />
<example-cmp @animate( [out]="myDynamicCSSClasses" ) />

<other-example-cmp (animate.out)="animateFn($event)" />
<other-example-cmp @animate( (out)="animateFn($event)" ) />

Consequences:

  • no directives / old animations named animate (forbidden),
  • special treatment compared to regular directives (but I guess it would be more or less the same with the current proposal),
  • newcomers can flag the feature as directives without any issue (no special syntax, ...). One day, there will be a "what???" moment and that's it!

Just an idea: I hope I haven't missed anything obvious!

You must be logged in to vote
1 reply
@thePunderWoman
Comment options

thePunderWoman Jun 23, 2025
Collaborator Author

@mauriziocescon Yeah we've had similar conversations about directives and how to refer to these. We've also been discussing selectorless syntax. Look for more on that in the future.

Comment options

I heard that the team is moving to native CSS styles from the Material team when proposing animation improvements, and finally here it is! The new solution is quite flexible and ergonomic, and I especially like that the function pattern supports third party animation libraries.

Btw, I guess the Vue team is the first to come up with the idea to toggle classes for animations. Evan You 👍


Q1: No. I personally is very against writing plain styles in the template.

Q2: I do prefer having animate.in. I think it would make the animation behaviors more predictable by looking only at the template.

Q3: I propose animation.enter and animation.leave, for maximum semantic correctness and symmetry. Using verbs for bindings just feels off to me, so I prefer animation over animate. I prefer enter and leave because they are professional and symmetric.

Q4: I prefer Option 2. Why should we introduce a magic method if there is a Web standard for extending events, which is perfect for our use case? In practice, rather than new Promise and stuff, we can create async helper methods to wrap the animation logic, so it would simply be: event.waitUtil(performFadeIn(event))

Q5: I would like to manually re-trigger enter and leave animations. I can imagine there are a lot of edge cases to handle but I still would like to re-trigger them if possible.


One feature that I really missed in the new API is to block child animations when parent animations are performing, and the ability to manually start or delay child animations.

You must be logged in to vote
1 reply
@thePunderWoman
Comment options

thePunderWoman Jun 24, 2025
Collaborator Author

This API is intentionally less complex than @angular/animations. The child animations control is something that should be easily accomplished programmatically using signals.

Comment options

Nice to see some input/discussion. I already wondered after the previous discussions around animations that we'd be seeing something like this. Good to get some input.

I would prefer enter/leave as that tells me more regarding what animation to expect. To me in/out can also relate to the direction or influence of the animation.

What I do wonder, for many animations I also need to do classes while it is animating. A common use case is not showing overflow scrollbars while the component is shrinking. Or alignment issues that may arise. Or making sure that the element animates between x and y. And so on. So that we move from something that is hidden, to something is animating, to something that is visible to something that is animating again and to something that is hidden once more. Where do these events/classes take place? Is this the part while animating or is this the hidden/visible parts? Am I right to assume that you would combine this with an @if or something and that the enter/leave are classes that take place while showing/hiding?

You must be logged in to vote
1 reply
@thePunderWoman
Comment options

thePunderWoman Jun 23, 2025
Collaborator Author

@Martinspire The classes in animate.in and animate.out only get added when the animation is occuring, then get removed. So you should be able to handle all of that behavior with the classes you specify.

Comment options

Discussion Question 1: Should these options support setting styles directly like ngStyle bindings? (see example)

I don't believe that's necessary. Given that both string/array values are supported, this should make Tailwind and other atomic CSS be able to do similar to what ngStyle does anyway.

Discussion Question 2: Is animate.in strictly necessary given the platform supports this behavior already?

I don't feel strongly here. I would prefer using @starting-style, but the argument for symmetry makes some sense. If it's tree-shakeable, I don't see any downside (except larger API surface for the Angular team).

Discussion Question 3: What is your preference on the naming? animate.in and animate.out? animate.enter and animate.leave? Something else?

While I do like the terseness of in/out, I wonder if it would be better to align with @starting-style, such as using perhaps start/end or start/exit. I don't think enter/leave is better in any way, other than that it helps keep terminology from @angular/animations. I think my preferred order would be:

  1. [animate.start] + [animate.end]
  2. [animate.start] + [animate.exit]
  3. [animate.in] + [animate.out]
  4. [animate.enter] + [animate.leave]

Discussion Question 4: Which of these 2 options for using functions is the most ideal to you, and why? Do you have an alternative suggestion?

Option 2, for a couple of reasons. A Promise fits well with the mental model of something that "completes later" (inherent with transition/animation), as well as fitting better with existing element.getAnimations() and the Animation.finished property.

animateFn = (event: AnimationEvent) => {
  const allDone = Promise.all(event.element.getAnimations().map(a => a.finished));
  event.waitUntil(allDone);
}

The example provided for this option can be simplified using Promise.withResolvers(). This adds minimal overhead to the callback-based example, and the API makes it aligns well with other web platform features like Service Workers.

animateFn = (event: AnimationEvent) => {
  const { promise, resolve } = Promise.withResolvers();
  animate(event.element, {
    x: '16rem',
    delay: 500,
    loop: 2,
    alternate: true,
    onComplete: resolve,
  });
  event.waitUntil(promise);
}

Discussion Question 5: What would you want out of testing tools for animations?

Not sure I would actually test animations personally in unit tests. As long as the everything looks right after enter/leave animations.

You must be logged in to vote
0 replies
Comment options

1. Should animate.in and animate.out support direct styles (like ngStyle)?
Yes, but only for simple cases, like an option that u can have. It would be useful to set quick animations without creating CSS classes (I know its not a good practice but still). For example:

<div [animate.out]="{ opacity: 0, transition: '0.5s' }"></div>

But for complex animations, CSS classes (and tailwind) are still better because they keep the code clean.

2. Is animate.in really needed if CSS already has @starting-styles?
To make Angular more consistent, Yes. If we have animate.out, it’s good to have animate.in too as well. Also, animate.in can automatically remove CSS classes after the animation as said, which @starting-styles doesn’t do.

3. What names are better? animate.in/out or animate.enter/leave?
animate.enter and animate.leave are clearer names imo. They are easier to understand, especially for new developers. Other frameworks like Vue use similar names (enter/leave, I don't think they changed it), so it’s a familiar pattern.

4. Which is better callback function or ExtendableEvent?
The first option for me, is simpler and more familiar, why familiar? 'cus GSAP and Anime.js they are using callbacks like (onComplete) so it feels natural. Again most Angular developers already use callbacks in other parts of their apps. Promises can be confusing for beginners as well. Also, the 4-second timeout is a good safety feature imo

5. What should testing tools for animations do?
Just test animations when needed, tools to check if animations work correctly especially with third party libraries.

You must be logged in to vote
0 replies
Comment options

Just an idea regarding Q3:

The @ is already well-known for animation, so how about dropping the animate. prefix and directly using @enter and @leave instead?

You must be logged in to vote
3 replies
@Pietrucci-Blacher
Comment options

The prefix is a bit of a convention, like for attribute binding, so I don't think it would make much sense not to use it 🫤

@thomashilzendegen
Comment options

A little more verbose, but yes, it looks like class. or style. but doesn't it behave a little bit differently? The latter two are more of an assignment, but the animate. is more like a trigger...

@thePunderWoman
Comment options

thePunderWoman Jun 24, 2025
Collaborator Author

The @ prefix was specific to the @angular/animations library. Since they both will coexist for at time, re-using the @ symbol would be confusing and likely breaking.

Comment options

Nice to see something like GSAP into this.

it reminders me of something I did back in the day building overlays:

<div class="canvas_container">
@animate(in: {
  opacity:0
  x:-300px // or any other measure that indicate out of the stage, container, or screen...
  delay: 3000 // or some sort of function or promise that observe other elements so animations can be chained or handled manually
  transform: {...}
}, out:{
  opacity:1
  x:600px // or any other measure that indicate out of the stage, container, or screen...
  delay: 100 // or some sort of function or promise that observe other elements so animations can be chained or handled manually
  transform: {...}
}, ... other parameters?: {...}) {
<component />
}
</div>

parameters could be anything like events, callbacks, etc...

notes on in/out: from the perspective of a canvas, elements go in our out. enter or leave are probably synonyms with the same purpose, however a mouse can "enter" or "leave" an element, in our out acts more on the context that elements on the DOM are in the screen as elements of a scene in a canvas.

You must be logged in to vote
0 replies
Comment options

Question 1: being able to set a css custom variable in a ngStyle like pattern would be great to reuse css animations with variable parameters. For example creating a from/to animation with variable heights or the current mouse position.

You must be logged in to vote
2 replies
@denisyilmaz
Comment options

While reading my own comment again I realized that for my described scenario I just could use ngStyle itself and set specific css variables for the in/out animation there. So I'm not sure I would need that described feature here.

@alxhub
Comment options

alxhub Jun 24, 2025
Collaborator

[style.--css-var] also works, no need for NgStyle.

Comment options

Question 2: being able to set a specific (dynamic) css class on enter of an element would be beneficial to further fine grain an intro animation. Like the direction of which an element should animate from. Another example would be an animation via GSAP that would can use a local signal for its calculation when an element is added.

You must be logged in to vote
0 replies
Comment options

Question 3: is the naming convention changing overall for bindings in Angular?
Otherwise my first instinct would have been that the naming should be camel case bindings such as [animateIn] (for classes) and (onAnimateIn) (for callbacks)

You must be logged in to vote
4 replies
@thePunderWoman
Comment options

thePunderWoman Jun 24, 2025
Collaborator Author

Not overall, but for this feature, yes.

@csvn
Comment options

The . in animation bindings actually make it align very will with class ([class.my-class]) and style ([style.font-size.px]) bindings. Personally I like [animate.in] because it feels similar and creates a kind of "Animation" namespace for bindings.

@denisyilmaz
Comment options

Got it.

I kind of like the writing as well, just felt different from the other template directives/attributes.

Then animate.in/out would be my preferred names. Somehow I feel the elements are added into the DOM rather than entering the view (which enter/leave feel like).
By the way, would a animate.enter be possible in the future with built in InViewport support (in combination with @defer(on viewport) even)?

@alxhub
Comment options

alxhub Jun 24, 2025
Collaborator

Angular uses .-namespacing to indicate a special type of binding: class., style., attr., etc. animate. is another usage of this.

Comment options

I really like this proposal. It seems much simpler and more ergonomic compared to the old @angular/animations. I can’t wait to use it in my applications. Thanks for modernizing animations in Angular!

You must be logged in to vote
0 replies
Comment options

Discussion Question 1: Should these options support setting styles directly like ngStyle bindings? (see [example]

This encourages sloppy code, and is particularly detrimental in large applications with reusable and extendable components, and annoys designers when developers drop inline styles in html.

Discussion Question 2: Is animate.in strictly necessary given the platform supports this behavior already?

For consistency, yes. I shouldn't need to take two separate approaches for each side of the same coin.

Discussion Question 3: What is your preference on the naming? animate.in and animate.out? animate.enter and animate.leave? Something else?

Enter and Leave are consistent with the Angular Animations :enter and :leave aliases which might smooth transition from that package (I know I'm holding off on moving to native CSS animation on out product for now because of the extra work to deal with animating out)

Discussion Question 4: Which of these 2 options for using functions is the most ideal to you, and why?

The callback function looks cleaner and is easier to understand for people who generally like to avoid directly using Promises.

Discussion Question 5: What would you want out of testing tools for animations?

Disabling when running test suite (already mentioned), and that the animation (and the correct animation) is being triggered when expected.

You must be logged in to vote
2 replies
@reduckted
Comment options

This encourages sloppy code, and is particularly detrimental in large applications with reusable and extendable components, and annoys designers when developers drop inline styles in html.

Encourages? I don't think so. Allows? Sure.
But you can use @angular-eslint/template/no-inline-styles if you don't want inline styles.

@thePunderWoman
Comment options

thePunderWoman Jun 27, 2025
Collaborator Author

I don't need any encouragement for writing sloppy code. I am quite good at it already. 😆

Comment options

Great work on this proposal! I believe this is exactly what I needed for applying animations in Angular.
Here is my feedback on the questions


Q1: I believe that for consistency, we should avoid supporting direct style setting options like ngStyle bindings here, as ngStyle and ngClass are moving towards deprecation.

Q3: I prefer enter and leave. In and out could be misleading, suggesting easing functions rather than the creation or destruction of a component.

Additional Suggestion:
One thing I'd like to mention is that in most cases, I would probably use a string of CSS classes to trigger the animation. However, when applying a CSS animation this way, the current proposal doesn't seem to offer a clear way to determine when the 'in' animation has completed. It would be great to have an optional parameter for a callback to handle this, similar to the example below:

[animate.in]="{
  classes: myDynamicCSSClasses,
  onComplete: () => {
    // ... do something after the animation ends
  }
}"
You must be logged in to vote
2 replies
@thePunderWoman
Comment options

thePunderWoman Jun 27, 2025
Collaborator Author

So for classes on animate.in, they get automatically removed when the animation finishes. We also wouldn't need to add any specific callbacks here, because it's just using the standard browser events for onAnimationEnd / onTransitionEnd. You are able to listen to those events as well.

@fireonmac
Comment options

So for classes on animate.in, they get automatically removed when the animation finishes. We also wouldn't need to add any specific callbacks here, because it's just using the standard browser events for onAnimationEnd / onTransitionEnd. You are able to listen to those events as well.

Thank you for the clarification! That makes sense.

Relying on the standard animationend and transitionend events is a solid approach. My only thought was about the developer experience when animate.in and animate.out are used on the same element. In that scenario, we would need to inspect the animationName within a single event listener to determine whether the "in" or "out" animation has just completed.

To potentially make this a bit more declarative and align with existing Angular syntaxes like [style.width.px], I was wondering if something like the following could be a consideration.

[animate.in]="cssClasses"
[animate.in.start]="onInAnimationStart($event)"
[animate.in.end]="onInAnimationEnd($event)"

Just a thought to share. Thanks again for the great proposal!

Comment options

hi,

1. Animation naming-style

both animation name in, out does make sense for naming animation, however enter and leave can every body know that about when element or component inserted or removed from DOM,

we can associate or bind a class names or arrays of class names to enter & leave

<component [enter]='class-name-expression'/></component>
<component leave='[class1, 'class2', 'class3, ... class-n']'/>

2. Animation callback

both enter & leave should be handle animation event like (start, complete, restart if user refresh while prev animation not complete yet)

type AnimationCallbackHandler {
     onStart: () => void | {},
     onComplete: () => void | {},
     onRestart: () => void | {}
}

and associate this type with enter and leave

<component (enter.onStart)='callback function when animation start'/'>
<component (enter.onComplete)='callback function when animateion complete'/'>
<component (enter.onRestart)='callback function when animation restart''/>

3. Animate Route Navigation

combine this new style of animation with modern navigation style view-transition

You must be logged in to vote
0 replies
Comment options

In which version this update will be introduced ?

You must be logged in to vote
1 reply
@thePunderWoman
Comment options

thePunderWoman Jun 30, 2025
Collaborator Author

We don't typically comment on when proposed features would actually be released during an RFC. We're happy you're excited to know though!

Comment options

Discussion Question 1: Should these options support setting styles directly like ngStyle bindings? (see example)

While I'm generally for giving a bit more freedom, it would add unnecessary typing complexity to directives. Unless you want to make something like animate.out and animate.out.style.

Discussion Question 2: Is animate.in strictly necessary given the platform supports this behavior already?

What if I want to use GSAP for in and out - using animate.out directive and defining "in" animation in completely different place I would need to look for then? Not saying about tracking whether some condition changes to show the element and then waiting for next render to actually put it into DOM.

Having animate.in would not only provide opposite option but also allow to keep things consistent (one place for in and out animations; same way of defining them). As I understand argument with CSS' @starting-style, some people may see it as more consistent and clear to use both directives than defining "in" and "out" in two completely different places. I wouldn't force opinions here

Discussion Question 3: What is your preference on the naming? animate.in and animate.out? animate.enter and animate.leave? Something else?

in and out is shorter and explanatory enough

Discussion Question 4: Which of these 2 options for using functions is the most ideal to you, and why?

I see event.animationComplete() as more clear way in case of events

Discussion Question 5: What would you want out of testing tools for animations?

Possibility to disable animations in e2e testing to speed them up - not sure if you covered this in FAQ#5. In general some possibility to switch animations dynamically would be good if possible (eg. user decided to enable reduced motion)

Other than that some benchmarking / performance

You must be logged in to vote
0 replies
Comment options

Discussion Question 1: Should these options support setting styles directly like ngStyle bindings? (see example)

No, but mostly because I don't like ngStyle either and don't think animations should need it.

Discussion Question 2: Is animate.in strictly necessary given the platform supports this behavior already?

Strictly necessary ? No. Sensible? Yes, for the reason you mentioned of having a symmetrical API. If you provide animate.out, given the history of the angular animations package, I expect also to find an animate.in, even if technically it's not that necessary.

Discussion Question 3: What is your preference on the naming? animate.in and animate.out? animate.enter and animate.leave? Something else?

enter and leave, solely for consistent vocabulary with angular animations and because they're solid words for this.

Discussion Question 4: Which of these 2 options for using functions is the most ideal to you, and why? Do you have an alternative suggestion?

No preference

Discussion Question 5: What would you want out of testing tools for animations?

At my workplace we mostly want to be able to test "Is this specific animation running?". I think for that purpose it would already suffice if I could check if the CSS class associated with the animation is currently being applied or not.

The rest would just be able to use tick to skip to the end timepoint of an animation which should then trigger corresponding aniimationEnd events (whose effects would then be tested for).

You must be logged in to vote
0 replies
Comment options

Did you consider the implication this will have on routing transitions?
Maybe the adding of the event binding feature could be coupled with some modification to current Router, so the animation.out could be bound to something like a routeLeaving Event?

You must be logged in to vote
1 reply
@thePunderWoman
Comment options

thePunderWoman Jun 30, 2025
Collaborator Author

We've actually already added support for view transitions in the router, which is our recommended approach for route animations.

Comment options

I wish Angular supported global animations for @if(cond) {} blocks, with the ability to override them like @if(userData, custom_animation_name) {}. This would be especially helpful when dealing with async data fetched from the backend, so that some animation plays when the data is retrieved.

You must be logged in to vote
0 replies
Comment options

Will it also work seamlessly with the @defer when actually deferred loading should fire first then animation? They will definitely elevate the visual experience along with some neat lazy loading.

You must be logged in to vote
8 replies
@syzgod
Comment options

These animations will fire when elements enter or exit the DOM. So if they enter the DOM after a defer block loads, they'll fire.

So currently not possible to animate a skeleton and then fire the @defer block? Like on the @defer the trigger would be animate.finish or similar. I probably overcomplicate it though.

@thePunderWoman
Comment options

thePunderWoman Jul 1, 2025
Collaborator Author

You could always subscribe to the native browser animationEnd / transitionEnd events and use that to set a signal which would trigger a defer block.

@denisyilmaz
Comment options

Not with the way things are planned, no. In this case, if you rely on standard @starting-styles CSS, it should fire those animations, but it would not handle dehydrated code, as the javascript has not yet been fetched / loaded.

Just to make sure I understand: this means in the "hydration step" a "dehydrated" DOM Element gets replaced by the "hydrated" Angular component? And therefore the @starting-styles would fire? I thought the DOM Element is reused in the hydration step.

I'm just wondering, if the Angular Animation system is moving towards this CSS based animation approach: couldn't there be a ng-dehydrated (or ng-rehydrated class) being applied to the dehydrated/hydrated elements? I guess you had something like this in the hydration demo (where dehydrated elements where b/w and hydrated had colors applied to it).

@thePunderWoman
Comment options

thePunderWoman Jul 1, 2025
Collaborator Author

@denisyilmaz @starting-styles is a CSS standard. If the CSS is present, this will happen regardless of whether JS is present or not. It's irrespective of hydration. We're also aiming to keep these animation bindings pretty close to the CSS metal. We're not intending to add a bunch of stuff on top of it.

@denisyilmaz
Comment options

@denisyilmaz @starting-styles is a CSS standard. If the CSS is present, this will happen regardless of whether JS is present or not. It's irrespective of hydration. We're also aiming to keep these animation bindings pretty close to the CSS metal. We're not intending to add a bunch of stuff on top of it.

Thanks, yes sure. Maybe my initial question was misleading: for SSR rendered elements that get hydrated it would be great to animate them when they arrive in the viewport (without a custom directive using the Intersection Observer API) which I thought would be a good usage of @defer(hydrate on viewport). But I understand this is mixing things too much.

@starting-styles would be triggered for deferred blocks whenever they are attached to the DOM – no matter if in/outside the current viewport, right?

Background is this: We used the current angular animation system a lot with a InViewport directive that triggers a nice staggered "fade in" animation for elements. So I'm just trying to understand how with the new system this could work and/or be simplified by using built in systems (like combining animate.in within a @defer(hydrate…) block).

I know we could do this as well now with scroll-driven CSS animation (which we are also using with the view progress timeline), but for more complex animations we love the angular animation logic with its different states etc.

Hope this make sense what I'm writing 😆

Comment options

My comments will be from the perspective of library maintainer. So this is written under assumption that component code isnt directly available to the consumer.

Discussion Question 1: Should these options support setting styles directly like ngStyle bindings?

Yes! This would allow to make a simple Input to pass in animation styles. Supporting only class based animation will require to break encapsulation with ng-deep or global styles which is dangerous and risks leaks. Style object can be declared as const and reused safely.

Discussion Question 2: Is animate.in strictly necessary given the platform supports this behavior already?

Yes! This is very important for dynamically configured animations. as well for consistency. I would hate to have half of my code use new API for out and rest is some mix of different approaches. Also for some complex library animation configs its important to have extra control via callbacks.

For example: I would trigger parallel animations in some components/directives which would in turn trigger stagger animations inside to create layout with multiple columns where each column staggers its elements in parallel. The animation itself is configured via DI and can be overridden per element. Elements also remember their animation in case they were toggled via @if . I would need in out callback functionality to make something like this without @angular/animations

We should also add support for animate.in and animate.out in hostbindigs and @HostBinding() to make it possible to encapsulate reusable animation logic in directives.

Discussion Question 3: What is your preference on the naming? animate.in and animate.out? animate.enter and animate.leave? Something else?

in-out is more concise. It is clear its a new API not like enter leave of the old animations.

Discussion Question 4: Which of these 2 options for using functions is the most ideal to you, and why? Do you have an alternative suggestion?

Option 1: Callback function. If i were a junior developer I would not want to think what it this all extra syntax is for or have some funny async await ideas. I dont see any need to make it a promise because animateFn wont be awaited. it relies on callback in both cases(resolve()) just with extra syntax on second case.

You must be logged in to vote
0 replies
Comment options

Q1: Yes
Q2: No
Q3: animate.out
Q4: callback

You must be logged in to vote
0 replies
Comment options

Questions

Q1: No, makes it to complicated IMHO
Q2: Technically No, but I also sucker for symmetry so Yes
Q3: enter/ leave but in/ out is as fine for me
Q4: option 1 - the callback option
Q5: as just mentioned, to be able to skip them for unit tests AND something that any js framework can provide (I assume) to manipulate time, by ticking forward or backward, but in a real browser (for visual regression tests)

Template Syntax

I'd like to provide some feedback and a potential alternative for the proposed template syntax, regarding the use of directive-like bindings ([] and ()).

First, I'm curious if there's a public design doc outlining the decisions, including the pros and cons, behind the current syntax choices. Understanding your thoughts here would be very helpful IMHO.

My primary motivation for asking is that I agree with the decision that this new functionality should not be a directive. Based on that, I'd like to propose a different syntax that clearly shows a compile-time transformation rather than mimicking a directive.

I suggest we re-use the @ symbol, which has already been introduced for flow control and defer, to serve as the official indicator for compiler-based code sections. This would provide a consistent visual cue for developers.

Here are a few examples of how this could look:

HTML

<example-cmp @animate.out="'fancy-animation-class'" />
<example-cmp @animate.out="myDynamicCSSClasses" />
<other-example-cmp @animate.out="animateFn($event)" />

Alternatively, to differentiate between static and dynamic values while maintaining the @prefix:

HTML

<example-cmp @animate.out="fancy-animation-class" />
<example-cmp @[animate.out]="myDynamicCSSClasses" />
<other-example-cmp @(animate.out)="animateFn($event)" />

I believe this approach would visually enhance the code and leverage an already established symbol within the framework.
Looking forward to your thoughts on this alternative syntax.

You must be logged in to vote
1 reply
@thePunderWoman
Comment options

thePunderWoman Jul 7, 2025
Collaborator Author

I mentioned this in an earlier suggestion, but reusing the @ symbol would be a massively breaking change since the current animations package relies on it for parsing. There's a lot of framework code that looks for this @ specifically. So we wouldn't be able to re-use that without a lot of problems.

I'll add that this syntax is not block syntax. Defer blocks and control flow are their own lines. They define the start of a block. The animations code here is not the same in that regard. It exists as an attribute on an element. Using an @ in this case would be mixing those concepts.

Comment options

Does the framework actually need an 'animations' feature?

First let me start by saying that I have not been privy to the many dicussions that have occured amoungst the team about this feature and while I am certain that they were quite thorough in investigating all possiblities, something keeps nagging me - is this the right solution to the stated problem? It seems to me that the problem that is trying to be solved is that the framework needs to know when it is safe to remove an element from the DOM if there is an 'exit' animation applied to it. Also, it is stated and keeps getting repeated that the animate.in is not necessary because it can be handled with native CSS. Why add something that is not necessary.

Isn't this a life-cycle issue? Shouldn't it perhaps be part of the life-cycle of destroying a component. You mentioned the event.waitUntil method on ExtendableEvent. Wouldn't a similar API on DestroyRef maybe (just a guess, I am not sure of the actual framework process of removing a component) be the solution. We could then use the native browser events animationEnd and transisitonEnd in some way to delay the removal of the component.

Just my CDN$0.02

You must be logged in to vote
3 replies
@SanderElias
Comment options

Not everything in a view is an Angular component. You still want to be able to animate out DOM elements that don't have an Angular life cycle on them.

Ideally, you want a CSS native solution for this. But as that is not a short-term option, we (Angular devs at large) need a solution.
This is the closest we can come. Also, it will make refactoring it to a CSS native solution easy(ish), once it arrives.

@andrewalderson
Comment options

I woke up this morning thinking about the issue of not everything in a template having an Angular life-cycle. I remember seeing a demo years ago that animated the Material table rows as they were added and removed from the table. In thinking about this now I can see the benefits of this approach because it is a solution that is applied to the template - where it belongs.

@thePunderWoman
Comment options

thePunderWoman Jul 8, 2025
Collaborator Author

Sander has it right here. Animations apply to all kinds of nodes, and not just components. So we definitely do need a solution for dealing with element removal. Sander also mentioned there is no native solution for this right now. So without a framework level solution, animating elements away is not trivial with native CSS. Other web frameworks have very similar APIs to this proposed one, and our goal here was to keep this as close to the platform as we could.

Comment options

Instead of animate.out, can we think about onDestroy?

Example:

<other-example-cmp (onDestroy)="destroyFn($event)" />

And extend the event like below:

event.cleanUpComplete()

Or

event.waitUntil(cleanUpPromise)
You must be logged in to vote
1 reply
@thePunderWoman
Comment options

thePunderWoman Jul 8, 2025
Collaborator Author

This would likely get confused with the Component onDestroy, which wouldn't be ideal. Animations apply to more than just components, and DOM nodes don't have an OnDestroy like a component does.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
📢
RFCs
Labels
None yet
Morty Proxy This is a proxified and sanitized view of the page, visit original site.