Using animations in your app (HTML)

Use animations in your JavaScript app for a fast, fluid user experience consistent with other Windows apps. Animations provide transitions between UI states that make your app feel responsive to user input. Animations give the user helpful visual cues, but do not intrude on the app's operation or distract from it.

To download a sample that demonstrates many of the concepts discussed in this topic, see the HTML animation library sample. Code examples in this topic come from that sample.

Roadmap: How does this topic relate to others? See:

Animation sources

Some animations are built into Windows controls. When you use those controls, you get their animations with no further coding. However, you also have the option of using the Animation Library. When you use the Animation Library, you can create custom animations for your app while retaining the Windows design look and feel.

  • Using built-in animations
  • Using the Animation Library

Using built-in animations

Some animations are automatically provided for you as part of Windows.

Windows system animations

Some system-provided animations apply to all app windows. Your app does not have to explicitly do anything to get these system animations. However, there are a few key points that you should be aware of, which are discussed here.

  • App launch
  • Rotation and resize changes
  • Entrance and exit of the on-screen keyboard

App launch

Two animations are involved in an app launch. The first animation shows the launch of your app between its selection on the Start screen and the appearance of its splash screen. The second animation crossfades from the splash screen to your app's background. We recommend that your app also runs its own animation to display its first page of content once the splash screen goes away.

Rotation and resize changes

When your app updates its layout in response to a size or orientation change, system animations make the transition smooth.

Entrance and exit of the on-screen keyboard

The on-screen keyboard appears automatically when a text input control in your app receives focus. By default, your app's content automatically scrolls to keep the input control visible on the screen, if necessary. No special action is required by your app.

Windows controls and HTML controls

The following controls include animations. We recommend that you use these controls whenever possible.

In addition, when using common HTML form controls such as buttons, checkboxes, and drop-down menus, you do not need to provide animations in response to user actions like clicking or hovering. These controls either already include any necessary animations or do not require animations because they use a color change or some other visual indicator to provide user feedback.

The styling for all of these elements is applied automatically through the WinJS CSS and UI.js files in the Microsoft Visual Studio project templates.

Using the Animation Library

You can add custom animations to your app by using the Animation Library. The Animation Library is a suite of animations that embody the personality of motion design in Windows and Windows Phone. These animations are available to developers for use within their apps, through the functions that make up the WinJS.UI.Animation namespace. For more information about the Animation Library, including videos and guidelines for each animation, see Animating your UI.

You must provide your own animations in these cases:

  • To move an entire control
  • To change the contents of your app
  • To navigate between pages in your app

All animations provided through the Animation Library are implemented using CSS animations and CSS transitions. The Animation Library animations animate the "opacity" and "transform" CSS properties.

  • Using the element and offset parameters in an Animation Library function
  • Animation types
  • Scheduling animations
  • Enabling and disabling animations

Using the element and offset parameters in an Animation Library function

Many of the Animation Library functions include the same parameters, used in the same way.

element

Many Animation Library functions take a Document Object Model (DOM) element as the animation target. This parameter can be expressed in the following ways:

  • As the special value "undefined", which means that the animation has no such target
  • As a single object
  • As a JavaScript array (possibly empty) of elements.
  • As a NodeList (for example, the result of querySelectorAll)
  • As an HTMLCollection

offset

The offset parameter is part of element animations and transitions that include a translation. These animations move the element either from its offset position to its final position, or from its current position to its offset position.

Some animations have recommended offsets that you can use by passing null or undefined as the offset argument, or omitting the argument altogether. Whenever possible, you should use these default offsets, which provide these benefits:

  • Better animation performance
  • Automatic mirroring in right-to-left apps
  • Designer-recommended translation distance, automatically adjusted (in applicable animations) when your app is resized

Unless you have a compelling design exception, these animations should always use the default offset:

For other Animation Library animations, the offset can be app-specific, based on your particular UI. All of the following functions have a default offset that will be used if no specific offset is provided, but you will usually specify an offset based on the design of your app.

You can provide the offset parameter in several forms:

  • As the special value "undefined", which you can specify explicitly in the call or implicitly by omitting the parameter value. The undefined value means that the animation's default offset will be used.

  • As a single JavaScript object of this form:

    { top: string, left: string, rtlflip: true | false }

    For example:

    { top: "12px", left: "0px", rtlflip: true }

    The object must have properties named top and left that represent the offset applied at the beginning of the animation. Any valid CSS units can be used to express the offset. In this form, the offset applies to all elements involved in the animation.

    The rtlflip parameter flips the values to a right-to-left alignment. It affects the left parameter and changes its sign. For instance, 10 px becomes -10px. This parameter is optional and can be omitted. If it is omitted, the default value is false.

  • As a JavaScript array (possibly empty) of the {top: ..., left: ..., rtlflip: ...} objects discussed above. In this case, each object in the array applies to a single element in the animation, in the order given; the first object applies to the first element, the second to the second, and so on. If the number of elements is greater than the number of objects in this array, then the last element in the array applies to all of the remaining elements. The only animation that typically requires an array of offset records is dragBetweenEnter. For other animations, it's usually best to pass only a single offset record to be used on all elements.

The Promise return value

The return value for all Animation Library animations is a Promise object. This object's done or then method can be used to track when the animation is completed. The Promise object also provides a cancel method through which you can cancel a running animation.

Animation types

The animations in the Animation Library are one of three types; element animation, element transition, or layout transition. Each type has a different implementation pattern.

  • Element animations
  • Element transitions
  • Layout transitions

Element animations

Element animations are implemented as CSS animations. Element animations do not change the state of the element; they are animations on top of the current state. For example, the showPanel animation is an element animation that slides a panel, such as a task pane, in from the edge of the screen. The showPanel animation animates a translation of the panel from a developer provided offset to the element's current position.

To use an element animation, you set the final state of the element. In the following example, the myPanel element is already in its final location before it is shown, but it's not visible. To show the panel, your code sets the panel element's opacity to 1 and then trigger the animation. As long as these steps occur within the same function, the opacity change will not take effect until the animation begins. The panel appears in its offset position and then animates into its actual position.


                                                
myPanel.style.opacity = "1";
WinJS.UI.Animation.showPanel(myPanel, { top: "0px", left: "350px" });                                       
                                            

To hide the panel, the process is reversed. First, your code must call hidePanel, which animates the panel from its current position to the offset position. When the animation is complete, your code sets the opacity to 0 to hide the element. If you fail to include the opacity change, the element will appear to snap back to its original position at the end of the animation and still be visible on screen.


                                                
WinJS.UI.Animation.hidePanel(myPanel, { top: "0px", left: "350px" })
    .then(function () { myPanel.style.opacity = "0"; });                                       
                                            

Here are the element animations in the Animation Library:

Function Description
showEdgeUI Slides edge-based UI into view. Animates translation of the target element from an offset to its current position.
hideEdgeUI Slides edge-based UI out of view. Animates translation of the target element from its current position to an offset.
showPanel Slides large edge-based panels into view. Animates translation of the target element from an offset to its current position.
hidePanel Slides large edge-based panels out of view. Animates translation of the target element from its current position to an offset.
showPopup Displays contextual UI on top of the view. Animates opacity to 1 and animates translation from an offset to its current position.
hidePopup Hides contextual UI. Animates opacity to 0.
updateBadge Updates a numerical badge. Animates opacity to 1 and animates translation from an offset to its current position.

 

Element transitions

Element transitions are implemented as CSS transitions. Element transitions change the state of an element by transitioning the CSS property to the value defined by the animation.

Many of the element transitions in the Animation Library come as a pair of animations meant to be used together. The state change applied by one animation in the pair is reversed by the other animation. For example, the fadeIn animation transitions the element's opacity to 1, while the fadeOut animation transitions the element's opacity to 0.

Some animations in the Animation Library use a combination of element animations and element transitions. For example, the enterContent animation transitions the content's opacity to 1 while it animates a translation from an offset to its current position.

The animations in the Animation Library that use either element transitions or both element transitions and element animations are listed here:

Function Description
fadeIn Shows transient elements or controls. Transitions opacity to 1.
fadeOut Hides transient elements or controls. Transitions opacity to 0.
enterContent Animates a single element or a set of content into view. Transitions opacity to 1 and animates translation from an offset to its current position.
exitContent Animates a single element or a set of content out of view. Transitions opacity to 0.
enterPage Animates the full contents of a page into view. Transitions opacity to 1 and animates translation from an offset to its current position.
exitPage Animates the full contents of a page out of view. Transitions opacity to 0.
crossFade Refreshes a content area. Transitions opacity to 1 on the incoming content and to 0 on the outgoing content.
pointerDown Gives visual feedback when the user taps or clicks on a tile. Transitions the scale to a slightly smaller value.
pointerUp Gives visual feedback when the user releases a tap or click on a tile. Restores the scale to its full size.
dragSourceStart Gives visual feedback when the user begins a drag-and-drop operation. Transitions the scale to a slightly larger value and reduces its opacity. This animation also transitions the scale of surrounding (affected) elements to a slightly smaller value.
dragSourceEnd Gives visual feedback when the user completes a drag-and-drop operation by dropping the dragged object. Reverses the animations performed by dragSourceStart.
dragBetweenEnter Gives visual feedback that the elements currently below the dragged object will move out of the way if the dragged object is dropped in that spot. Transitions the transform property of the affected objects to an offset.
dragBetweenLeave Gives visual feedback that a dragged object has left drop zone by reversing the animation performed by dragBetweenEnter.
swipeSelect Transitions a tile to a swipe-selected state. Transitions the opacity of the tile to 0 while it transitions the opacity of the offset "selected" visual to 1.
swipeDeselect Transitions a tile to a swipe-deselected state. Transitions the opacity of the offset "selected" visual to 0 while it transitions the opacity of the original tile to 1.
swipeReveal Gives a visual hint to the user that a tile supports the swipe interaction. Transitions translation from current position to an offset.
turnstileBackwardIn Rotates an element clockwise onto the page.
turnstileBackwardOut Rotates an element clockwise off the page.
turnstileForwardIn Rotates an element counterclockwise onto the page.
turnstileForwardOut Rotates an element counterclockwise off the page.
slideDown Slides elements off through the bottom of the screen.
slideUp Slides elements up into view from the bottom of the screen.
slideLeftIn Slides elements in from the left side of the screen.
slideLeftOut Slides elements out through the left side of the screen.
slideRightIn Slides elements in from the right side of the screen.
slideRightOut Slides elements out through the right side of the screen.
continuumBackwardIn Scales down an incoming page while scaling, rotating, and translating an incoming item.
continuumBackwardOut Scales, rotates, and translates an outgoing page as it is removed.
continuumForwardIn Brings an item onto the screen, scaling up the incoming page while scaling, rotating, and translating the incoming item.
continuumForwardOut Removes an item from the screen, scaling down the outgoing page while scaling, rotating, and translating the outgoing item.

 

Layout transitions

Layout transition animations in the Animation Library are more complex than element animations or element transitions. Layout transition animations typically involve multiple elements and result in a layout change. However, the animation functions can't make assumptions about how that layout change happens. For example, in the reposition animation, an element moves from point A to point B. There are many different ways this can occur, such as changing the width of the element, its offset, or its margin or padding.

For layout transitions, the Animation Library provides a creation function and returns an object with a .execute() method. The calling pattern for these animations is:

  1. Call the appropriate create animation function. The current position of the target elements is collected.
  2. The app performs its layout changes in whatever way it chooses.
  3. The app calls the execute method on the object returned by the create function to trigger the animation. This collects the new position of the target elements and animates them from their original position to the new position.
  4. The execute method returns a Promise object that can be used in the normal way.

The following example shows the add-to-list animation, which is used to animate the insertion of an item to the top of a list. When createAddToListAnimation is called, the positions of all elements passed in the affectedItems collection are recorded. All elements whose position could be affected by the arrival of the new item are included in this collection.

After createAddToListAnimation is called, the example inserts the new item at the top of the list. In the following code, list is the div element that contains the list items. Calling the element's insertBefore method performs the actual addition of newItem to the top of the list. This insertion causes all of the other items in the list to change position. You are free to change the position of the affectedItems collection in any way you choose.

Finally, the example triggers the animation to move the new list item into place by calling the execute method of the object returned by createAddToListAnimation.


                                                
var addToList = WinJS.UI.Animation.createAddToListAnimation(newItem, affectedItems);
list.insertBefore(newItem, list.firstChild);
addToList.execute();
                                            

The layout transition animation creation functions in the Animation Library are listed here:

Function Description
createExpandAnimation Shows additional inline information. Moves other content to make room if necessary.
createCollapseAnimation Hides inline content. Collapses other content if necessary.
createRepositionAnimation Moves an element into a new position.
createAddToListAnimation Adds an item to a list.
createDeleteFromListAnimation Removes an item from a list.
createAddToSearchListAnimation Adds an item to a list while filtering search results.
createDeleteFromSearchListAnimation Removes an item from a list while filtering search results.
createPeekAnimation Shows a peek animation on a tile. The content of a peek tile scrolls up and down within the tile space to display the full communication.

 

Scheduling animations

To complete a complex scenario, it's often necessary to run different animations on different parts of the UI. For example, when you delete an email, you might need to remove the deleted email from the list and then display the next email message. In most cases it's best to run both animations at the same time for a shorter overall duration. The next sections discuss issues that you must keep in mind in those scenarios.

Interrupting animations

An animation or transition on an element is interrupted if another animation or transition on the same CSS property is triggered. When this happens, the first animation or transition is cancelled in accordance with the CSS3 specification. CSS transitions interrupt each other smoothly and fluidly. However, in the case of CSS animations, they show a transition of the CSS property on top of the element, while the actual CSS property value in the element remains unchanged. Interrupting a CSS animation jarringly snaps back to the property's original value and is not recommended. With CSS animations, it is usually better to wait until the first animation ends before you begin a second animation. For more information, see Waiting for an animation to finish.

Scenario Result
CSS animation interrupts a CSS animation The CSS property that is being animated reverts to its true state and then begins the new animation. This can result in visual unpleasantness.
CSS animation interrupts a transition The transition is smoothly interrupted at whatever point it was at and begins animating to the new end value from its current value.
CSS transition interrupts a transition The transition is smoothly interrupted at whatever point it was at and begins transitioning to the new end value from its current value.
CSS transition interrupts an animation The CSS property that is being animated reverts to its true state and then begins the new transition. This can result in visual unpleasantness.

 

Canceling animations

Any running Animation Library animation can be canceled through the cancel method of the Promise object returned by the animation function.

Waiting for an animation to finish

To perform an action when an animation is complete, pass a callback function to the done or then method of the Promise object returned by the animation function. This is useful in such cases as waiting to remove an item from the DOM until its exit animation completes, or when chaining multiple animations. An example is shown here, with the callback function fading the target out only after it has completed fading in.


                                                
WinJS.UI.Animation.fadeIn(target)
       .then(function () { WinJS.UI.Animation.fadeOut(target); });
                                            

We recommend that you do not use a JavaScript timer to determine when the animation has completed. Doing so is unreliable; the timer could complete before or after the animation and its timing can vary based on the hardware and other processes running on the UI thread.

Enabling and disabling animations

Note  Windows: All Animation Library animations are disabled in response to the 'Disable all unnecessary animations' system setting, found in the Ease of Access item in the Control Panel, under Make the computer easier to see. When this setting is selected, all animations that are not essential to the basic functionality of the app are turned off. This typically means all animations except for some game animations necessary to play that game. The animation library animations and custom animations that use executeAnimation or executeTransition respond to this setting automatically. If you create a custom animation, then your code must explicitly listen for this setting.

It is up to you, as the developer, whether Animation Library animations that you use in your app respond to the WinJS.UI.enableAnimations and WinJS.UI.disableAnimations functions.

Optimizing animation performance

Show app responsiveness through animation

To provide a good overall user experience, your app needs to feel fast and responsive to user actions. When used correctly, animations can help make your app feel more responsive by providing the right user feedback at the right time.

Animations in response to a user action must begin as quickly as possible. This is critical in informing the user that their action was successful and something is happening in response. If there is further work to be done to complete a transition such as loading a new page, do this work after the user response animation has been triggered.

Use independent animations

The animation platform for JavaScript apps enables certain types of animations to run on a separate, hardware-accelerated, system thread independent of the UI thread. This type of animation is called an independent animation. An animation running in the UI thread is called a dependent animation. Because they do not have to compete with other actions occurring in the UI thread, independent animations are consistently smoother than dependent animations.

All animations in the Animation Library can be run as independent animations, but there are considerations that you must address in the implementation of your app in order to do so. For more information on qualifying your animation function calls to run as independent animations, see Independent Composition: Rendering and Compositing in Internet Explorer.

Minimize the number of elements animating at once

Whenever possible, reduce the number of individual elements being animated. For example, rather than passing an array of elements to an animation, passing just the parent element means that the animation engine only needs to create a single animation operation.

Use default offsets

For Animation Library animations that include an offset parameter, use the default offset whenever possible. Not only will you get the design-recommended translation for that animation, but the performance will be better because the animation can use precalculated keyframes.

Default offsets also automatically mirror in right-to-left app, and, for some animations, the default offset automatically changes the amount of translation when the app is resized, to show the appropriate effect for the narrower view state.

Creating custom animations

You should use the Animation Library animations whenever possible. However, when you have a unique scenario and none of the built-in animations are what you need, you can create a custom animation.

There are two ways to implement a custom animation in JavaScript apps: through standard CSS3 animations and transitions or through the Animation Library helper functions executeAnimation and executeTransition.

Creating custom animations using standard CSS3 animations and transitions

CSS3 animations and transitions allow a flexible option that can create an animation or transition over a variety of CSS properties. For more information, see the Animations and Transitions topics.

When you choose to create your own animations, be aware of these points:

  • Animations or transitions over some CSS properties will not run as independent animations and can cause the entire page to redraw with every frame. This can cause a slow and jerky animation, which is a poor user experience. Avoid animating those properties in the implementation of your custom animations to ensure that your animations are run independently.
  • A custom CSS3 animation or transition cannot coexist simultaneously with an Animation Library animation on the same element.

Creating custom animations using executeAnimation and executeTranslation

The Animation Library functions executeAnimation and executeTransition are used by the Animation Library to run its own animations, and you can also use them for your custom animations. All animations and transitions executed by these functions can qualify to be run as independent animations and they can coexist with any stock Animation Library animations that are also running. The executeAnimation and executeTransition functions return a Promise object, in keeping with the rest of the Animation Library functions.

You can use these two functions on any animatable CSS properties. However, only the opacity and transform properties can be run as independent animations. If your app requires something more exotic, such as in-game animations, these functions might not be the right choice in your scenario.

When using the executeAnimation function, we recommend that you specify keyframes for the animation to get better performance.


                                
@keyframes custom-opacity-in    { from { opacity: 0; } to { opacity: 1; } }
                            

The following example shows a custom animation.


                                
function runCustomShowAnimation() {
    var showAnimation = WinJS.UI.executeAnimation(
        target,
        {
            keyframe: "custom-opacity-in",
            property: "opacity",
            delay: 0,
            duration: 500,
            timing: "linear",
            from: 0,
            to: 1
        }
    );
}
                            

The following example shows a custom transition


                                
function runCustomShowTransition() {
    var showTransition = WinJS.UI.executeTransition(
        target,
        {
            property: "opacity",
            delay: 0,
            duration: 500,
            timing: "linear",
            to: 1
        }
    );
}
                            

Combining custom animations and transitions

You can combine animations and transitions to create a custom storyboard. In the following examples, an animation and a transition are combined to achieve a simultaneous fade-in and sliding effect on the target element. The two parts of the storyboard are triggered independently through calls to executeAnimation and executeTransition, but they will begin at the same time.


                                
@keyframes custom-translate-in    { from { transform: translateY(50px); } to { transform: none; } }
                            

                                
function runCustomShowStoryboard() {
    var promise1 = WinJS.UI.executeAnimation(
        target,
        {
            keyframe: "custom-translate-in",
            property: "transform",
            delay: 0,
            duration: 367,
            timing: "cubic-bezier(0.1, 0.9, 0.2, 1)",
            from: "translate(50px)", 
            to: "none"
        });
    var promise2 = WinJS.UI.executeTransition(
        target,
        {
            property: "opacity",
            delay: 0,
            duration: 167,
            timing: "linear",
            to: 1
        });
    return WinJS.Promise.join([promise1, promise2]);
}
                            

Animating your UI (HTML)