Description Animation component
Availability
Experimental; no validations yet.
Work in progress.
Required Script <script async custom-element="amp-animation" src="https://cdn.ampproject.org/v0/amp-animation-0.1.js"></script>
Supported Layouts nodisplay

Overview

AMP Animations rely on Web Animations API to define and run animations in AMP documents.

Format

An amp-animation element defines such an animation as a JSON structure.

Top-level animation specification

The top-level object defines an overall animation process which consists of an arbitrary number of animation components defined as an animations array:

<amp-animation layout="nodisplay">
<script type="application/json">
{
  // Timing properties
  ...
  "animations": [
    {
      // Animation 1
    },
    ...
    {
      // Animation N
    }
  ]
}
</script>
</amp-animation>

Placement in DOM

Initially, <amp-animation> is only allowed to be placed as a direct child of <body> element. This restriction will be removed in the near future.

Animation component

Each animation component is a keyframes effect and is comprised of:

  • Target element(s) referenced by a selector
  • Media query
  • Timing properties
  • Keyframes
{
  "selector": "#target-id",
  "media": "(min-width:300px)",
  // Timing properties
  ...
  "keyframes": []
}

Media query

Media query can be specified using the media property. This attribute can contain any expression allowed for Window.matchMedia API.

If value is specified for an animation component, the animation component will only be included if the media query will match the current environment.

Timing properties

Top-level animation and animation components may contain timing properties. These properties are defined in detail in the AnimationEffectTimingProperties of the Web Animation spec. The set of properties allowed here includes:

Property Type Default Description
duration time 0 The animation duration. Either a numeric value in milliseconds or a CSS time value, e.g. `2s`.
delay time 0 The delay before animation starts executing. Either a numeric value in milliseconds or a CSS time value, e.g. `2s`.
endDelay time 0 The delay after the animation completes and before it's actually considered to be complete. Either a numeric value in milliseconds or a CSS time value, e.g. `2s`.
iterations number or
"Infinity" or
"infinite"
1 The number of times the animation effect repeats.
iterationStart number/CSS 0 The time offset at which the effect begins animating.
easing string "linear" The timing function used to scale the time to produce easing effects.
direction string "normal" One of "normal", "reverse", "alternate" or "alternate-reverse".
fill string "none" One of "none", "forwards", "backwards", "both", "auto".

All timing properties allow either a direct numeric/string values or CSS values. For instance, "duration" can be specified as 1000 or 1s or 1000ms. In addition, calc() and var() and other CSS expressions are also allowed.

An example of timing properties in JSON:

{
  ...
  "duration": "1s",
  "delay": 100,
  "endDelay": "var(--end-delay, 10ms)",
  "easing": "ease-in",
  "fill": "both"
  ...
}

Animation components inherit timing properties specified for the top-level animation.

Keyframes

Keyframes can be specified in numerous ways described in the keyframes section of the Web Animations spec.

Some typical examples of keyframes definitions are below.

Shorthand object-form "to" format specifies the final state at 100%:

{
  "keyframes": {"opacity": 0, "transform": "scale(2)"}
}

Shorthand object-form "from-to" format specifies the starting and final states at 0 and 100%:

{
  "keyframes": {
    "opacity": [1, 0],
    "transform": ["scale(1)", "scale(2)"]
  }
}

Shorthand object-form "value-array" format specifies multiple values for starting, final states and multiple (equal-spaced) offsets:

{
  "keyframes": {
    "opacity": [1, 0.1, 0],
    "transform": ["scale(1)", "scale(1.1)", "scale(2)"]
  }
}

The array-form specifies keyframes. Offsets are assigned automatically at 0, 100% and spaced evenly in-between:

{
  "keyframes": [
    {"opacity": 1, "transform": "scale(1)"},
    {"opacity": 0, "transform": "scale(2)"}
  ]
}

The array-form can also include "offset" explicitly:

{
  "keyframes": [
    {"opacity": 1, "transform": "scale(1)"},
    {"offset": 0.1, "opacity": 0.1, "transform": "scale(2)"},
    {"opacity": 0, "transform": "scale(3)"}
  ]
}

The array-form can also include "easing":

{
  "keyframes": [
    {"easing": "ease-out", "opacity": 1, "transform": "scale(1)"},
    {"opacity": 0, "transform": "scale(2)"}
  ]
}

For additional keyframes formats refer to Web Animations spec.

The property values allow any valid CSS values, including calc(), var() and other CSS expressions.

Whitelisted properties for keyframes

Not all CSS properties can be used in keyframes. Only CSS properties that modern browsers can optimize and animate quickly are whitelisted. This list will grow as more properties are confirmed to provide good performance. Currently the list contains:

  • opacity
  • transform
  • visibility

Notice that the use of vendor prefixed CSS properties is neither needed nor allowed.

Abbreviated forms of animation configuration

If the animation only involves a single element and a single keyframes effect is sufficient, the configuration can be reduced to this one animation component only. For instance:

<amp-animation layout="nodisplay">
<script type="application/json">
{
  "selector": "#target-id",
  "duration": "1s",
  "keyframes": {"opacity": 1}
}
</script>
</amp-animation>

If the animation is comprised of a list of components, but doesn't have top-level animation, the configuration can be reduced to an array of components. For instance:

<amp-animation layout="nodisplay">
<script type="application/json">
[
  {
    "selector": ".target-class",
    "duration": 1000,
    "keyframes": {"opacity": 1}
  },
  {
    "selector": ".target-class",
    "duration": 600,
    "delay": 400,
    "keyframes": {"transform": "scale(2)"}
  }
]
</script>
</amp-animation>

var() and calc() expressions

amp-animation allows use of var() and calc() expressions for timing and keyframes values.

For instance:

<amp-animation layout="nodisplay">
<script type="application/json">
[
  {
    "selector": ".target-class",
    "duration": "4s",
    "delay": "var(--delay)",
    "keyframes": {"transform": "translateX(calc(100vh + 20px))"}
  }
]
</script>
</amp-animation>

Both var() and calc() polyfilled on platforms that do not directly support them. var() properties are extracted from the corresponding target elements. However, it's unfortunately impossible to fully polyfill var(). Thus, where compatibility is important, it's strongly recommended to include default values in the var() expressions. For instance:

<amp-animation layout="nodisplay">
<script type="application/json">
[
  {
    "selector": ".target-class",
    "duration": "4s",
    "delay": "var(--delay, 100ms)",
  }
]
</script>
</amp-animation>

CSS extensions

amp-animation provides several CSS extensions for typical animations needs: rand(), width(), and height(). These functions can be used everywhere where CSS values can be used within amp-animation, including timing and keyframes values.

CSS rand() extension

The rand() function returns a random CSS value. There are two forms.

The form without arguments simply returns the random number between 0 and 1.

{
  "animation-delay": "calc(10s * rand())"
}

The second form has two arguments and returns the random value between these two arguments.

{
  "animation-delay": "rand(5s, 10s)"
}

CSS width() and height() extensions

The width() and height() extensions return the width/height of the animated element or the element specified by the selector. The returned value is in pixels, e.g. 100px.

The following forms are supported:

  • width() and height() - width/height of the animated element.
  • width('.selector') and height('.selector') - width/height of the element specified by the selector. Any CSS selector can be used. For instance, width('#container > li').
  • width(closest('.selector')) and height(closest('.selector')) - width/height of the element specified by the closest selector.

The width() and height() are epsecially useful for transforms. The left, top and similar CSS properties that can use % values to express animations proportional to container size. However, transform property interpretes % values differently - as a percent of the selected element. Thus, the width() and height() can be used to express transform animations in terms of container elements and similar.

These functions can be combined with calc(), var() and other CSS expressions. For instance:

{
  "transform": "translateX(calc(width('#container') + 10px))"
}

Triggering animation

The animation can be triggered via a trigger attribute or an on action.

trigger attribute

Currently, visibility is the only available value for the trigger attribute. The visibility triggers when the underlying document or embed are visible (in viewport).

For instance:

<amp-animation id="anim1" layout="nodisplay"
    trigger="visibility">
  ...
</amp-animation>

on action

For instance:

<amp-animation id="anim1" layout="nodisplay">
  ...
</amp-animation>
<button on="tap:anim1.activate">Animate</button>