@ngdoc overview @name Tutorial: 12 - Applying Animations @description
... ...Animations can now be created within the CSS code (`animations.css`) as well as the JavaScript code (`animations.js`). But before we start, let's create a new module which uses the ngAnimate module as a dependency just like we did before with `ngResource`. ## Module & Animations __`app/js/animations.js`.__
angular.module('phonecatAnimations', ['ngAnimate']).
  // ...
  // this module will later be used to define animations
  // ...
And now let's attach this module to our application module...
__`app/js/app.js`.__
// ...
angular.module('phonecat', [
  'ngRoute',
  'phonecatAnimations',
  'phonecatControllers',
  'phonecatFilters',
  'phonecatServices',
]).
// ...
Now, the phonecat module is animation aware. Let's make some animations!
## Animating ngRepeat with CSS Transition Animations
We'll start off by adding CSS transition animations to our `ngRepeat` directive present on the `phone-list.html` page.
First let's add an extra CSS class to our repeated element so that we can hook into it with our CSS animation code.
__`app/partials/phone-list.html`.__
{{phone.snippet}}
.phone-listing.ng-enter,
.phone-listing.ng-leave,
.phone-listing.ng-move {
  -webkit-transition: 0.5s linear all;
  -moz-transition: 0.5s linear all;
  -o-transition: 0.5s linear all;
  transition: 0.5s linear all;
}
.phone-listing.ng-enter,
.phone-listing.ng-move {
  opacity: 0;
  height: 0;
  overflow: hidden;
}
.phone-listing.ng-move.ng-move-active,
.phone-listing.ng-enter.ng-enter-active {
  opacity: 1;
  height: 120px;
}
.phone-listing.ng-leave {
  opacity: 1;
  overflow: hidden;
}
.phone-listing.ng-leave.ng-leave-active {
  opacity: 0;
  height: 0;
  padding-top: 0;
  padding-bottom: 0;
}
As you can see our `phone-listing` CSS class is combined together with the animation hooks that occur when items are
inserted info and removed from the list:
  * The `ng-enter` class is applied to the element when a new phone is added to the list and rendered on the page.
  * The `ng-move` class is applied when items are moved around in the list.
  * The `ng-leave` class is applied when they're removed from the list.
The phone listing items are added and removed depending on the data passed to the `ng-repeat` attribute.
For example, if the filter data changes the items will be animated in and out of the repeat list.
Something important to note is that when an animation occurs, two sets of CSS classes
are added to the element:
  1. a "starting" class that represents the style at the beginning of the animation
  2. an "active" class that represents the style at the end of the animation
The name of the starting class is the name of event that is fired (like `enter`, `move` or `leave`) prefixed with
`ng-`. So an `enter` event will result in a class called `ng-enter`.
The active class name is the same as the starting class's but with an `-active` suffix.
This two-class CSS naming convention allows the developer to craft an animation, beginning to end.
In our example above, elements expand from a height of **0** to **120 pixels** when items are added or moved,
around and collapsing the items before removing them from the list.
There's also a nice fade-in and fade-out effect that also occurs at the same time. All of this is handled
by the CSS transition declarations at the top of the example code above.
Although most modern browsers have good support for {@link http://caniuse.com/#feat=css-transitions CSS transitions}
and {@link http://caniuse.com/#feat=css-animation CSS animations}, IE9 and earlier do not.
If you want animations that are backwards-compatible with older browsers, consider using JavaScript-based animations,
which are described in detail below.
## Animating `ngView` with CSS Keyframe Animations
Next let's add an animation for transitions between route changes in `ngView`.
To start, let's add a new CSS class to our HTML like we did in the example above.
This time, instead of the `ng-repeat` element, let's add it to the element containing the ng-view directive.
In order to do this, we'll have to make some small changes to the HTML code so that we can have more control over our
animations between view changes.
__`app/partials/phone-list.html`.__
With this change, the `ng-view` directive is nested inside a parent element with a `view-container` CSS class. This class adds a `position: relative` style so that the positioning of the `ng-view` is relative to this parent as it animates transitions. With this in place, let's add the CSS for this transition animation to our `animations.css` file: __`app/css/animations.css`.__
.view-container {
  position: relative;
}
.view-frame.ng-enter, .view-frame.ng-leave {
  background: white;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}
.view-frame.ng-enter {
  -webkit-animation: 0.5s fade-in;
  -moz-animation: 0.5s fade-in;
  -o-animation: 0.5s fade-in;
  animation: 0.5s fade-in;
  z-index: 100;
}
.view-frame.ng-leave {
  -webkit-animation: 0.5s fade-out;
  -moz-animation: 0.5s fade-out;
  -o-animation: 0.5s fade-out;
  animation: 0.5s fade-out;
  z-index:99;
}
@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@-moz-keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@-webkit-keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
@-moz-keyframes fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
@-webkit-keyframes fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
/* don't forget about the vendor-prefixes! */
Nothing crazy here! Just a simple fade in and fade out effect between pages. The only out of the ordinary thing
here is that we're using absolute positioning to position the next page (identified via `ng-enter`) on top of the
previous page (the one that has the `ng-leave` class) while performing a cross fade animation in between. So
as the previous page is just about to be removed, it fades out while the new page fades in right on top of it.
Once the leave animation is over then element is removed and once the enter animation is complete then the
`ng-enter` and `ng-enter-active` CSS classes are removed from the element rendering it to be position itself
with its default CSS code (so no more absolute positioning once the animation is over). This works fluidly so
that pages flow naturally between route changes without anything jumping around.
The CSS classes applied (the start and end classes) are much the same as with `ng-repeat`. Each time a new page is
loaded the ng-view directive will create a copy of itself, download the template and append the contents. This
ensures that all views are contained within a single HTML element which allows for easy animation control.
For more on CSS animations, see the
{@link http://docs.webplatform.org/wiki/css/properties/animations Web Platform documentation}.
## Animating `ngClass` with JavaScript
Let's add another animation to our application. Switching to our `phone-detail.html` page,
we see that we have a nice thumbnail swapper. By clicking on the thumbnails listed on the page,
the profile phone image changes. But how can we change this around to add animations?
Lets think about it first,
basically when you click on a thumbnail image, you're changing the state of the profile image to reflect the newly
selected thumbnail image.
The best way to specify state changes within HTML is to use classes.
Much like before, how we used a CSS class to specify
an animation, this time the animation will occur whenever the CSS class itself changes.
Whenever a new phone thumbnail is selected, the state changes and the `.active` CSS class is added to the matching
profile image and the animation plays.
Let's get started and tweak our HTML code on the `phone-detail.html` page first:
__`app/partials/phone-detail.html`.__
![]()
{{phone.name}}
{{phone.description}}
angular.module('phonecatAnimations', ['ngAnimate'])
  .animation('.phone', function() {
    return {
      addClass : function(element, className, done) {
        if(className != 'active') {
          return;
        }
        element.css({
          position: 'absolute',
          top: 500,
          left: 0,
          display: 'block'
        });
        jQuery(element).animate({
          top: 0
        }, done);
        return function(cancel) {
          if(cancel) element.stop();
        };
      },
      removeClass : function(element, className, done) {
        if(className != 'active') return;
        element.css({
          position: 'absolute',
          left: 0,
          top: 0
        });
        jQuery(element).animate({
          top: -500
        }, done);
        return function(cancel) {
          if(cancel) element.stop();
        };
      }
    };
  });
Note that we're using {@link http://jquery.com/ jQuery} to implement the animation. jQuery
isn't required to do JavaScript animations with AngularJS, but we're going to use it because writing
your own JavaScript animation library is beyond the scope of this tutorial. For more on
`jQuery.animate`, see the {@link http://api.jquery.com/animate/ jQuery documentation}.