angular 2 animation vs css animation - when to use what?
The question is actually more javascript animation vs css animation (because angular2's animations are based on javascript-animation).
The answer is that when you can - use CSS animation.
Modern browsers uses different thread for CSS animation, so the javascript-thread is not affected by the CSS animations.
You can use the HTML5 Animation Speed Test to check the preformance of different frameworks (javscript-based) VS CSS animation in your browser.
In general:
Browsers are able to optimize rendering flows. In summary, we should always try to create our animations using CSS transitions/animations where possible. If your animations are really complex, you can may have to rely on JavaScript-based animations instead.
If you want to know specifically regarding the Angular2 animations - just inspect the element in your browser and check if the animation there is a CSS(transition/animationFrame based or javascript (you will be able to see values in the style
attribute change during the animation).
What is the purpose of Angular animations?
So I did some research and although I didn't find any argument for nor against Angular animations performance-wise (as already stated in the question above), there are very good arguments to use Angular animations feature-wise which should be good enough for purists who want to have CSS only in sheets, at least in certain cases.
Let me list some useful features where each alone makes a convincing case for Angular animations. Most of them can be found in Angular animations documentation:
Transition styles - these styles are only applied during transition from one state to another - only while an element is being animated, and one uses them like this:
transition('stateA => stateB', [style({...}), animate(100)])
Trying to do the same with CSS only might not be as expressive in terms of which previous state led to the next. And it can be outright clunky if the animation has to differ based on the initial state but the end state is the same.
The
void
state together with:enter
and:leave
aliases (void documentation, :leave and :enter documentation) - Let you animate elements being added or removed from the DOM.transition('stateA => void', animate(...))
This is very cool because previously, although it was easy enough to animate the addition, the removal was more complicated and required to trigger animation, wait till its end and only after that remove the element from the DOM, all with JS.
Automatic property calculation
'*'
(documentation) - Allows for performing traditionally difficult animations like height transitions for elements with dynamic height. This problem required either to set fixed height on element (inflexible), use max-height with tuned transition function (not perfect) or query element's height with JS (potentially causing unnecessary reflows). But now with Angular it is as easy as this:trigger('collapsible', [
state('expanded', style({ height: '*' })),
state('collapsed', style({ height: '0' })),
transition('expanded <=> collapsed', animate(100))
])And the animation is smooth and "complete" because the actual height of the element is used for the transition.
Animation callbacks (documentation) - this is something that wasn't possible with CSS animations (if not maybe emulated with
setTimeout
) and is handy eg. for debugging.Unlike stated in the question, it is actually possible to use instance fields as params in Angular animations, see this question. I find it much easier to use than manipulating CSS variables through DOM API as shown here on MDN, not mentioning the limited support in some browsers.
If you need any of the features listed above, Angular can be a better tool for the task. Also when there is many animations to manage in a component, and this is just my personal opinion, I find it easier to organize animations the Angular way than have them in sheets, where it is harder too see the relationships between them and various element states.
Angular Animation Performance State/Transition vs Query
Angular uses the web animations api, so it's not changing style properties through JavaScript and is therefore quite performant. You can check the performance of different animation frameworks (javascript-based) vs CSS with the HTML 5 Animation Speed Test.
The performance in different browsers is therefore dependent on the browser compatibility of the web animations api (unfortunately the section is not being maintained yet). But, according to the comment here, it is not fully supported yet across common browsers and is being polyfilled for Edge/Safari.
Change style class with Angular animation or similar
Css animations & binding to a class
Using grid is cool but there's not a nice way to achieve what you want with it
Try this on for size
https://stackblitz.com/edit/angular-jeamzb?file=src/app/app.component.ts
It's not your exact solution but I whipped it up to show you how you could do something like this
angular 2 ngIf and CSS transition/animation
update 4.1.0
Plunker
See also https://github.com/angular/angular/blob/master/CHANGELOG.md#400-rc1-2017-02-24
update 2.1.0
Plunker
For more details see Animations at angular.io
import { trigger, style, animate, transition } from '@angular/animations';
@Component({
selector: 'my-app',
animations: [
trigger(
'enterAnimation', [
transition(':enter', [
style({transform: 'translateX(100%)', opacity: 0}),
animate('500ms', style({transform: 'translateX(0)', opacity: 1}))
]),
transition(':leave', [
style({transform: 'translateX(0)', opacity: 1}),
animate('500ms', style({transform: 'translateX(100%)', opacity: 0}))
])
]
)
],
template: `
<button (click)="show = !show">toggle show ({{show}})</button>
<div *ngIf="show" [@enterAnimation]>xxx</div>
`
})
export class App {
show:boolean = false;
}
original
*ngIf
removes the element from the DOM when the expression becomes false
. You can't have a transition on a non-existing element.
Use instead hidden
:
<div class="note" [ngClass]="{'transition':show}" [hidden]="!show">
Apply animations on array length change
Here's an example:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
animations: [
trigger('simpleFadeAnimation', [
state('in', style({ opacity: 1, height: 100 + 'vh' })),
transition(':enter', [
style({ opacity: 0, height: 0 + 'vh' }),
animate(200),
]),
transition(
':leave',
animate(400, style({ opacity: 0, height: 0 + 'vh' }))
),
]),
],
})
export class AppComponent {
name = 'Angular';
data = ['A', 'B', 'C'];
add() {
const random = Math.floor(Math.random() * 10);
this.data.push(random.toString());
}
remove() {
this.data.pop();
}
removeThis(index) {
this.data.splice(index, 1);
}
}
Working example: https://stackblitz.com/edit/angular-animation-when-removing-jfle8g?file=src%2Fapp%2Fapp.component.ts
Animation in Angular 2 with pure CSS
It can be done easily with Angular animations. Here is your example updated: https://stackblitz.com/edit/angular-ivy-aw3zs3?file=src/app/card/card.component.ts
You just need to provied a state function to handle the transtion trigger.
transition((fromState: string, toState: string) => toState != fromState, [
// animations
])
And you need to link the animation with the target variable
<div class="card" [style]="style" [@cardChange]="card.card">
</div>
Related Topics
Css3 Radial Gradients with Rgba()
Is CSS Faster When You Are Specific
Center Output (Plots) in the Notebook
How to Create a CSS3 Gradient in Opera
Which Browsers Support Page Break Manipulation Using CSS and the Page-Break-Inside Element
Set Font Size of Angular Material Tooltip
Chrome:Text Blurry When Skew Back:Skew(-10Deg) -> Skew(10Deg)
How Can Block Container Establish Both Block and Inline Formatting Contexts at the Same Time
Stop Animation and Start Transition on Hover
How to Capitalize the First Letter of Each Word in CSS
Center Twitter Bootstrap 3 Glyphicons in Buttons
CSS Floats, Change Order on Mobile Layout
Stretch a Background Image in IE8
Display:None Doesn't Work on Outlook 2007
When Specifying a 0 Value in CSS, Should I Explicitly Mark the Units or Omit
Firefox Unexpected Line Break Using Floats & Overflow Hidden