Animating with AngularJS

by Brian Rinaldi on August 5, 2013

The modern web is always changing, and this article is more than two years old.

By Holly Schinsky

AngularJS recently came out with support for CSS3 transitions and animations, as well as JavaScript Animations. The support is part of version 1.1.4 (unstable build), but was changed and refined a bit in version 1.1.5 so you should start with that version when you check it out. I definitely think it’s worth trying because it allows you to add some fun interactions to your application quickly.

In this article I’ll explain a bit about how it all works and include links to a demo application I created to try things our for yourself. The source to the demo application is located on my GitHub account here as well. I also included some great resources in the form of links at the end of the post. There’s currently not a lot of documentation on this subject since it is so new, so I encourage you to check those out as well.

How it Works…

ngAnimate is the name of the new directive for AngularJS animation support. The way it’s applied is by adding the ng-animate attribute to any element containing one of the following directives in the list below:

The only exception to the above is when you create your own custom directive with animation support using the $animator service. This is discussed later in the article.

Each of these directives causes a change to the DOM, which is how the transition or animation is triggered. For instance, on an ngRepeat they will occur when the items are repeating, for ngShow/ngHide, when the element is being shown or hidden. You simply specify ng-animate on your element with the name of the classes you’ve defined in your CSS to perform the transitions or animations and they will be applied automatically. Of course, you need to ensure you specify the ng-animate on the same element where you have one of the directives mentioned above (ngRepeat, ngSwitch etc.) defined or nothing will happen.

Here’s a quick example of applying a scale type of transition the shorthand way (read on for notation details):

<ng-include ng-animate="'scale'" src="'partials/quote.html'"></ng-include>

Then in your CSS, you define a corresponding set of classes prefixed with scale that are used to trigger the transition or animation based on the type of event you want to animate for that directive. More info to come on this…

Supported Events

Certain events are supported for each of the directives you can animate. They vary per directive and it’s important to know which apply for a given directive when you’re defining your CSS classes to perform the animation.

Here’s the list:

Directive Events
ngIf enter/leave
ngInclude enter/leave
ngRepeat enter/leave/move
ngShow/ngHide show/hide
ngSwitch enter/leave
ngView enter/leave

 

The AngularJS docs describe exactly when those events occur for each of the directives supporting animations. So for instance the ngIf docs provide this description for the supported enter and leave events:

enter – happens just after the ngIf contents change and a new DOM element is created and injected into the ngIf container

leave – happens just before the ngIf contents are removed from the DOM

You can use this information to determine when your transitions and animations will actually be triggered.

CSS3 Transitions versus CSS3 Animations

ngAnimate can be used for both CSS3 animations and transitions, as well as JavaScript animations but that is beyond the scope of this article. I wanted to take a moment to briefly discuss the difference between CSS3 transitions and animations.

CSS3 Transitions
apply an effect to a style property for a certain duration. You can do things like fade, scale, move, slide, rotate, 3D effects etc.

CSS3 Animations are more complex than transitions and use keyframes to define different points to do things within the animation. These can be looped and auto-started. In addition, they don’t have to depend on a DOM change to trigger them.

The difference in using CSS3 transitions versus CSS3 animations with ngAnimate is all in the way the CSS classes are defined. A great example can be found in the AngularJS 1.1.5 docs for ngAnimate. I’m including it here too for easy reference:

CSS3 Transition Sample

.animate-enter {
 -webkit-transition: 1s linear all; /* Safari/Chrome */
 -moz-transition: 1s linear all; /* Firefox */
 -o-transition: 1s linear all; /* Opera */
 transition: 1s linear all; /* IE10+ and Future Browsers */

 /* The animation preparation code */
 opacity: 0;
}

/*
 Keep in mind that you want to combine both CSS
 classes together to avoid any CSS-specificity
 conflicts
*/
.animate-enter.animate-enter-active {
 /* The animation code itself */
 opacity: 1;
}

CSS3 Animation Sample

.animate-enter {
  -webkit-animation: enter_sequence 1s linear; /* Safari/Chrome */
  -moz-animation: enter_sequence 1s linear; /* Firefox */
  -o-animation: enter_sequence 1s linear; /* Opera */
  animation: enter_sequence 1s linear; /* IE10+ and Future Browsers */
}
@-webkit-keyframes enter_sequence {
  from { opacity:0; }
  to { opacity:1; }
}
@-moz-keyframes enter_sequence {
  from { opacity:0; }
  to { opacity:1; }
}
@-o-keyframes enter_sequence {
  from { opacity:0; }
  to { opacity:1; }
}
@keyframes enter_sequence {
  from { opacity:0; }
  to { opacity:1; }
}

When using ngAnimate for either of the above, the same syntax would be used to apply the directive, such as:

<div ng-view ng-animate="{enter: 'animate-enter'}"></div>

I highly recommend reading through the documentation for further details on how this is all handled.

Naming Conventions

When writing your CSS classes to apply your transitions or animations, you define two CSS classes for each supported event (enter, leave, show, hide, etc). One is used as a baseline class and the other is defined as an active class where the animation actually happens. There is a certain notation you need to use to define these classes. The base class is named as name-event (ie: slide-enter), whereas the active class is named the same with the keyword “active” appended to it (ie: slide-enter-active).

For example, using a fade type of effect on an ngShow or ngHide would require these 4 classes to be defined (since “show” and “hide” are the supported events for that directive):

.fade-show {
    -webkit-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    -moz-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    -ms-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    -o-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    white-space:nowrap;
    position:relative;
    overflow: hidden;
    text-overflow: clip;
}
.fade-show-active {
    opacity:1;
}
.fade-hide {
    -webkit-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    -moz-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    -ms-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    -o-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    white-space:nowrap;
    position:relative;
    overflow: hidden;
    text-overflow: clip;
}
.fade-hide-active {
    opacity:0;
}

Applying the CSS via ng-animate

Once you define all of your animations and transitions, you apply them via the ngAnimate directive. There are two ways you can describe which CSS classes to use, explicitly or shorthand. Both are shown below:

Explicit:
Here you explicitly name the class to apply for each supported event (enter, leave etc).

<div ng-view ng-animate="{enter: 'rotate-enter', leave: 'rotate-leave'}"></div>

Shorthand:
The shorthand way of applying them is through a name only, and then that name with the event appended is implied as the class name. So for instance, in the following, the resulting class names implied will be name-event or rotate-enter and rotate-leave, just as above:

<div ng-view ng-animate="'rotate'">

Check out the demo source or links provided for specific examples to understand the syntax further.

Customizing Animation

You can customize your AngularJS animation in different ways using the $animator service. You could create your own custom animation events or use the built-in ones like “enter” and “leave” with ng-animate in your own custom directive by accessing them off the $animator service.

You can also define custom events using the $animator.animate(myEvent,element) function, where myEvent is your own String and element is what to apply the transition or animation to.

I included an example of defining a custom directive and custom event in the demo application if you are interested in seeing how it works.

Related Resources