- Notifications
You must be signed in to change notification settings - Fork27k
[Complete] RFC - Animation In and Out#62212
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
Authors:@thePunderWoman The Angular team created Over the years, a few problems have emerged with We'd like to add two new native features to Angular: 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 ourcode 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
APILet's talk about the new API and how it will function. animate.outAnimating elements away from the DOM as they are being removed is a bit tricky to manage manually as there is no The Example usages <example-cmpanimate.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 animate.inThe need for an The If you are just using CSS classes, you do not need to use the Example usages <example-cmpanimate.in="pretty-animation-class"/><example-cmp[animate.in]="myDynamicCSSClasses"/><other-example-cmp(animate.in)="animateFn($event)"/> Discussion Question 2: Is Discussion Question 3: What is your preference on the naming? Animation Function details and optionsBoth Option 1: Callback functionThe native element reference allows you to call 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: ExtendableEventAnother option is to rely on the animateFn=(event:AnimationEvent)=>{constanimationPromise=newPromise((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 workScoped 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
|
BetaWas this translation helpful?Give feedback.
All reactions
👍 87🎉 11❤️ 42🚀 29
Replies: 35 comments 36 replies
-
Amazing idea! Q2: no Q3: animate.out |
BetaWas this translation helpful?Give feedback.
All reactions
👍 3
-
Great Idea. Especially the Callbacks will be very useful in my opinion. |
BetaWas this translation helpful?Give feedback.
All reactions
-
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) |
BetaWas this translation helpful?Give feedback.
All reactions
-
Q1: No, as it easily would lead to "too much logic in template", while not providing any additional use-cases. |
BetaWas this translation helpful?Give feedback.
All reactions
👍 2
-
Pretty much what I would have answered 👍 |
BetaWas this translation helpful?Give feedback.
All reactions
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
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 Q4: In this case 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. |
BetaWas this translation helpful?Give feedback.
All reactions
👍 1
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
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. 😅 Say, in a way changing the set of trade-offs: <!-- I'd jump directly to the potential selectorless notation (just a draft) --><example-cmpanimate.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:
Just an idea: I hope I haven't missed anything obvious! |
BetaWas this translation helpful?Give feedback.
All reactions
👍 2
-
@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. |
BetaWas this translation helpful?Give feedback.
All reactions
👍 1
-
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.
Q1: No. I personally is very against writing plain styles in the template. Q2: I do prefer having Q3: I propose 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 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. |
BetaWas this translation helpful?Give feedback.
All reactions
👍 1
-
This API is intentionally less complex than |
BetaWas this translation helpful?Give feedback.
All reactions
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
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? |
BetaWas this translation helpful?Give feedback.
All reactions
-
@Martinspire The classes in |
BetaWas this translation helpful?Give feedback.
All reactions
👍 3
-
I don't believe that's necessary. Given that both
I don't feel strongly here. I would prefer using
While I do like the terseness ofin/out, I wonder if it would be better to align with
Option 2, for a couple of reasons. A animateFn=(event:AnimationEvent)=>{constallDone=Promise.all(event.element.getAnimations().map(a=>a.finished));event.waitUntil(allDone);} The example provided for this option can be simplified using animateFn=(event:AnimationEvent)=>{const{ promise, resolve}=Promise.withResolvers();animate(event.element,{x:'16rem',delay:500,loop:2,alternate:true,onComplete:resolve,});event.waitUntil(promise);}
Not sure I would actually test animations personally in unit tests. As long as the everything looks right after enter/leave animations. |
BetaWas this translation helpful?Give feedback.
All reactions
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
1. Should animate.in and animate.out support direct styles (like ngStyle)? But for complex animations, CSS classes (and tailwind) are still better because they keep the code clean. 2. Is 3. What names are better? animate.in/out or animate.enter/leave? 4. Which is better callback function or ExtendableEvent? 5. What should testing tools for animations do? |
BetaWas this translation helpful?Give feedback.
All reactions
-
Just an idea regarding Q3: The |
BetaWas this translation helpful?Give feedback.
All reactions
-
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 🫤 |
BetaWas this translation helpful?Give feedback.
All reactions
👍 1
-
A little more verbose, but yes, it looks like |
BetaWas this translation helpful?Give feedback.
All reactions
👍 2
-
The |
BetaWas this translation helpful?Give feedback.
All reactions
👍 5
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
Nice to see something like GSAP into this. it reminders me of something I did back in the day building overlays: <divclass="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. |
BetaWas this translation helpful?Give feedback.
All reactions
-
Question 1: being able to set a css custom variable in a |
BetaWas this translation helpful?Give feedback.
All reactions
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
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. |
BetaWas this translation helpful?Give feedback.
All reactions
👍 1
-
|
BetaWas this translation helpful?Give feedback.
All reactions
👍 3
-
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. |
BetaWas this translation helpful?Give feedback.
All reactions
-
Question 3: is the naming convention changing overall for bindings in Angular? |
BetaWas this translation helpful?Give feedback.
All reactions
-
Not overall, but for this feature, yes. |
BetaWas this translation helpful?Give feedback.
All reactions
-
The |
BetaWas this translation helpful?Give feedback.
All reactions
👍 2
-
Got it. I kind of like the writing as well, just felt different from the other template directives/attributes. Then |
BetaWas this translation helpful?Give feedback.
All reactions
-
Angular uses |
BetaWas this translation helpful?Give feedback.
All reactions
👍 2
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
I really like this proposal. It seems much simpler and more ergonomic compared to the old |
BetaWas this translation helpful?Give feedback.
All reactions
-
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.
For consistency, yes. I shouldn't need to take two separate approaches for each side of the same coin.
Enter and Leave are consistent with the Angular Animations
The callback function looks cleaner and is easier to understand for people who generally like to avoid directly using Promises.
Disabling when running test suite (already mentioned), and that the animation (and the correct animation) is being triggered when expected. |
BetaWas this translation helpful?Give feedback.
All reactions
-
Encourages? I don't think so. Allows? Sure. |
BetaWas this translation helpful?Give feedback.
All reactions
-
I don't need any encouragement for writing sloppy code. I am quite good at it already. 😆 |
BetaWas this translation helpful?Give feedback.
All reactions
😄 3
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
Great work on this proposal! I believe this is exactly what I needed for applying animations in Angular. 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: [animate.in]="{classes:myDynamicCSSClasses,onComplete:()=>{// ... do something after the animation ends}}" |
BetaWas this translation helpful?Give feedback.
All reactions
-
So for classes on |
BetaWas this translation helpful?Give feedback.
All reactions
-
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! |
BetaWas this translation helpful?Give feedback.
All reactions
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
hi, 1. Animation naming-styleboth animation namein,out does make sense for naming animation, howeverenter andleave 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 toenter &leave 2. Animation callbackboth enter & leave should be handle animation event like (start, complete, restart if user refresh while prev animation not complete yet) and associate this type withenter andleave 3. Animate Route Navigationcombine this new style of animation with modern navigation styleview-transition |
BetaWas this translation helpful?Give feedback.
All reactions
-
In which version this update will be introduced ? |
BetaWas this translation helpful?Give feedback.
All reactions
-
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! |
BetaWas this translation helpful?Give feedback.
All reactions
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
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
What if I want to use GSAP for in and out - using Having
I see
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 |
BetaWas this translation helpful?Give feedback.
All reactions
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
Discussion Question 1: Should these options support setting styles directly like ngStyle bindings? (seeexample)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 |
BetaWas this translation helpful?Give feedback.
All reactions
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
Did you consider the implication this will have on routing transitions? |
BetaWas this translation helpful?Give feedback.
All reactions
-
We've actually already added support for view transitions in the router, which is our recommended approach for route animations. |
BetaWas this translation helpful?Give feedback.
All reactions
-
I wish Angular supported global animations for |
BetaWas this translation helpful?Give feedback.
All reactions
👀 1
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
Will it also work seamlessly with the |
BetaWas this translation helpful?Give feedback.
All reactions
-
So currently not possible to animate a skeleton and then fire the |
BetaWas this translation helpful?Give feedback.
All reactions
-
You could always subscribe to the native browser animationEnd / transitionEnd events and use that to set a signal which would trigger a defer block. |
BetaWas this translation helpful?Give feedback.
All reactions
👍 1
-
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 I'm just wondering, if the Angular Animation system is moving towards this CSS based animation approach: couldn't there be a |
BetaWas this translation helpful?Give feedback.
All reactions
-
@denisyilmaz |
BetaWas this translation helpful?Give feedback.
All reactions
👍 1
-
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
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 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 😆 |
BetaWas this translation helpful?Give feedback.
All reactions
-
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.
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.
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 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 We should also add support for animate.in and animate.out in hostbindigs and
in-out is more concise. It is clear its a new API not like enter leave of the old animations.
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 |
BetaWas this translation helpful?Give feedback.
All reactions
-
Q1: Yes |
BetaWas this translation helpful?Give feedback.
All reactions
-
QuestionsQ1:No, makes it to complicated IMHO Template SyntaxI'd like to provide some feedback and a potential alternative for the proposed template syntax, regarding the use of directive-like bindings ( 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 shouldnot 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 Here are a few examples of how this could look: HTML Alternatively, to differentiate between static and dynamic values while maintaining the HTML I believe this approach would visually enhance the code and leverage an already established symbol within the framework. |
BetaWas this translation helpful?Give feedback.
All reactions
👍 1👎 1
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
I mentioned this in an earlier suggestion, but reusing the 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 |
BetaWas this translation helpful?Give feedback.
All reactions
-
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 Isn't this a life-cycle issue? Shouldn't it perhaps be part of the life-cycle of destroying a component. You mentioned the Just my CDN$0.02 |
BetaWas this translation helpful?Give feedback.
All reactions
-
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. |
BetaWas this translation helpful?Give feedback.
All reactions
-
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. |
BetaWas this translation helpful?Give feedback.
All reactions
-
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. |
BetaWas this translation helpful?Give feedback.
All reactions
-
Instead of Example: <other-example-cmp(onDestroy)="destroyFn($event)"/> And extend the event like below: event.cleanUpComplete() Or event.waitUntil(cleanUpPromise) |
BetaWas this translation helpful?Give feedback.
All reactions
-
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. |
BetaWas this translation helpful?Give feedback.