A Guide to CSS Transitions in AngularJS

in code

Animated elements are extremely useful in modern user interfaces and utilized by nearly every web and mobile app these days. Typically an animation would be triggered by hovering-over or clicking an element. With Angular, the options for animating elements become endless, and its probably easier than you think to get started. In this guide I explore CSS-based transitions in AngularJS.

Animations vs Transitions

Standard animations and transitions are created using CSS's animation and transition properties. The two methods are similar in that they both alter CSS properties over a specified amount of time. For example, changing the background-color of an element.

Beyond that the two methods are very different for a variety of reasons:

  • how the animation is triggered
  • the complexity of animation possible
  • options for looping
  • hooks for interacting with the animation via javascript

For more detail on the differences between animations and transitions read this great article by Kirupa.

For the purpose of this article I'm only using transitions though many of the methods can be applied to animations too. Transitions are useful when you want to animate between two states based on an interaction - the user clicking or hovering, or the addition or removal of an element. Here's a simple example of a CSS transition triggered by hovering over an element.

HTML

<button>Sign Up</button>  

CSS (using transitions)

button {
  background-color:tan;
  transition:all linear 0.5s;
}

button:hover {
  background-color:wheat;
}

Transitions in Angular##

Adding transitions in Angular (v.1.3+) is deceptively simple. I tinkered for several hours before I reached my AHA moment so hopefully this guide can save others some time.

There are two ways to add transitions in Angular - with CSS or JS. CSS-based transitions use only CSS classes, while the JS method triggers animations that are registered via module.animation(). The examples below will only cover the CSS method.

Here was my epiphany regarding transitions in Angular:

Angular dynamically adds and removes specific CSS classes to elements, allowing you to add standard CSS transitions.

In other words you don't have to do anything in your Angular code. Angular adds and removes classes from elements, providing hooks for adding transitions. We'll cover the specifics of the CSS classes shortly.

Installation####

To get started with transitions you'll first need to add the ngAnimate module to your app.

Include the angular-animate.js in your HTML:

<script src="angular.js">
<script src="angular-animate.js">

Then add the ngAnimate module as a dependency:

angular.module('app', ['ngAnimate']);

Transition-aware directives

To add a transition to an element the element needs one of the following Angular directives attached:

  • ngShow/ngHide
  • ngRepeat
  • ngView
  • ngInclude
  • ngSwitch
  • ngIf
  • ngClass
  • form
  • ngModel
  • ngMessage/ngMessages

For example:

<div ng-show="showThisDiv">This Div is Visible</div>

What ngAnimate does####

When Angular encounters an element using one of these directives it dynamically applies utility classes to the element, making it easy to attach CSS transitions. The classes applied depend on the directive being used.

Example####

Going back to the previous example using ng-show, if showThisDiv returns (or is changed to) false Angular will add a class of ng-hide to the element.

<div ng-show="showThisDiv=false" class="box ng-hide">This Div is Visible</div>

Changing showThisDiv to true will result in the ng-hide class being removed.

The addition/removal of the .ng-hide class allows us to create the transition with some simple CSS:

.box {
  transition:all ease-out 0.5s;
  opacity: 0;
}

.box.ng-hide {
  opacity:1;
}

Here's a more useful example showing how to create a simple animated dropdown:

Clicking the Menu bar toggles the toggleDropdown variable between true and false causing the dropdown to have the .ng-hide class added and removed with each click. The addition of some simple CSS completes the transition.

Other Directives##

The other directives work similarly, with unique classes being dynamically applied depending on the directive.

It's not worth repeating the docs verbatim so for specifics on what classes are added to each directive and what triggers the classes head over to the Angular docs. While there are a few classes specific to certain directives follow one of 2 patterns.

For example, several directives (ng-repeat, ng-view, ng-include, ng-switch, ng-if and ng-messages) use variations of of .enter and .leave.

The remaining directives ('ng-class, form, ng-model and ng-messages) use variations of .add and .remove.

Variations?####

I have yet to find clear documentation on all the variations so it requires some DOM watching in your favorite inspector to figure it out. Here's the basic gist of it.

Returning to the ng-show example from the beginning - when ng-show evaluates to false Angular will temporarily add a .ng-hide-add class during the transition, then remove it at the end of the transition. Similarly, when ng-show is true a class of .ng-hide-remove is temporarily added during the transition.

With ng-if

Attaching ng-if to an element will dynamically inject .ng-enter and .ng-leave classes as the ng-if statement evaluates to true and false respectively. In addition to these 2 classes it will also inject .ng-enter-active and .ng-leave-active. The former being added temporarily as the element is transitioning to .ng-enter and the latter being added while the element is transitioning to .ng-leave.

These additional hooks give us the ability to create transitions between the two ng-if states. Here's the dropdown example from before using ng-if instead of ng-show.

With ng-class

The ng-class directive uses variations of .add and .remove by appending add and remove onto the classes in the ng-class expression. In the example below I'm using

ng-class="{'show-dropdown': vm.toggleDropdown}"

causing the .show-dropdown class to be added and removed as vm.toggleDropdown alternates between true and false respectively. Angular also adds utility classes of .show-dropdown-remove-active and .show-dropdown-add-active, giving us enough hooks to add the transition we want.

Wrapping Up##

Angular's ngAnimate module enables endless options for adding useful animations to your app. This guide is merely the tip of the iceberg and I encourage you to dive deeper into Angular's animation features.

Comments