Skip to content

Latest commit

 

History

History
1607 lines (1292 loc) · 64.2 KB

amp-story.md

File metadata and controls

1607 lines (1292 loc) · 64.2 KB
$category@ formats teaser
presentation
websites
text
A rich, visual storytelling format.

amp-story

Description A rich, visual storytelling format.
Availability
Required Script <script async custom-element="amp-story" src="https://cdn.ampproject.org/v0/amp-story-1.0.js"></script>
Supported Layouts none
Examples

{% call callout('Important', type='caution') %} This component is experimental and under active development. For any issues, please file a GitHub issue. {% endcall %}

[TOC]

Version notes

Version Description
1.0 Current version, since 2018-07-16.
0.1 Initial implementation. Deprecated, and will be removed on 2019-03-19

Migrating from 0.1 to 1.0

As of 2018-07-16, version 0.1 is considered deprecated, and will be removed on 2019-03-19. This may cause minor breaking changes, as your stories will automatically be upgraded to use version 1.0. We recommend manually migrating your pages to version 1.0 before this date to ensure functionality and proper design.

New bookend capabilities

We've added new capabilities to the amp-stories bookend, enabling richer component support and visual layouts. Some of the changes include:

  • Share providers are sorted according to the JSON configuration.
  • New bookend components:
    • Call to action links
    • Text box
    • Portrait and landscape cards

To use these new capabilities, add an <amp-story-bookend> tag as the last child of your <amp-story> with the required attributes like so:

<amp-story standalone>
  <amp-story-page id="cover">
    ...
  </amp-story-page>
  <!-- `src` and `layout=nodisplay` are required. -->
  <amp-story-bookend src="bookendv1.json" layout="nodisplay">
  </amp-story-bookend>
<amp-story>

Learn more about the new components and how to specify them in the JSON configuration in the amp-story-bookend section.

New metadata requirements

We've added new metadata attributes to the <amp-story> element. These metadata attributes will be used for displaying a preview of the story across the AMP stories ecosystem. For example, these attributes can be used to render an engaging preview link in the bookend of a related story. Providing these attributes will also help ensure your story is future-proof for rich, embedded experiences in AMP stories surfaces to come.

<!-- `title`, `publisher`, `publisher-logo-src` and `poster-portrait-src` will soon be required. -->
<amp-story standalone title="My Story"
    publisher="The AMP Team"
    publisher-logo-src="https://example.com/logo/1x1.png"
    poster-portrait-src="https://example.com/my-story/poster/3x4.jpg">

<!-- `poster-square-src` and `poster-landscape-src` are optional, but strongly recommended. -->
<amp-story standalone title="My Story"
    publisher="The AMP Team"
    publisher-logo-src="https://example.com/logo/1x1.png"
    poster-portrait-src="https://example.com/my-story/poster/3x4.jpg"
    poster-square-src="https://example.com/my-story/poster/1x1.jpg"
    poster-landscape-src="https://example.com/my-story/poster/4x3.jpg">

Note that these metadata attributes supplement and do not replace any Structured Data (e.g. JSON-LD) on the page. We still recommend adding Structured Data to all your AMP pages, including AMP stories.

The new attributes:

ATTRIBUTE DESCRIPTION
title [required] The title of the story.
publisher [required] The name of the story's publisher.
publisher-logo-src [required] The publisher's logo in square format (1x1 aspect ratio).
poster-portrait-src [required] The story poster in portrait format (3x4 aspect ratio).
poster-square-src The story poster in square format (1x1 aspect ratio).
poster-landscape-src The story poster in landscape format (4x3 aspect ratio).

publisher-logo-src guidelines

The following guidelines apply to the image for the publisher logo:

  • The file should be a raster file, such as .jpg, .png, or .gif. Avoid vector files, such as .svg or .eps.
  • Avoid animated images, such as animated gifs.
  • The graphic part of the logo should be legible on the background color.
Logo with blue text on white background Preferred Logo with white text on blue background Preferred Logo with blue text on blue background Avoid this
  • The logo shape should be a square, not a rectangle.
  • The background color should not be transparent.
  • Use one logo per brand that is consistent across AMP stories.
  • The logo should be at least 96x96 pixels.

Poster guidelines (for poster-portrait-src, poster-landscape-src, and poster-square-src)

The following guidelines apply to the image for the story poster image(s):

  • The poster image should be representative of the entire AMP story.
  • The poster image should be visible to the user when the user begins the AMP story. However, the image file URL used in the metadata does not have to match exactly the URL used on the first page of the story. The URL used in the metadata can include sizing, cropping, or minor styling changes for the preview purpose.
  • The poster image should be a raster file, such as .jpg, .png, or .gif. Avoid vector files, such as .svg or .eps.
  • The poster image should be in 3x4 aspect ratio for portrait, 4x3 for landscape, and 1x1 for square.
  • If the poster image is derived from a frame in a video, the thumbnail should be representative of the video. For example, the first frame in a video is often not representative.
  • Each poster image should meet the recommended minimium size:
    • Portrait: 696px x 928px
    • Landscape: 928px x 696px
    • Square: 928px x 928px

Overview

The amp-story extension provides a new format for displaying visual content that you can assemble into a story-telling experience. With an AMP story, you can provide users with bite-sized, visually rich information and content.

AMP Story Example

AMP story format

An AMP story is a complete AMP HTML document that is comprised of pages, within the pages are layers, within the layers are AMP & HTML elements, like media, analytics, text, and so on.

AMP story tag hierarchy

Boilerplate

The following markup is a decent starting point or boilerplate. Copy this and save it to a file with a .html extension.

<!doctype html>
<html amp lang="en">
  <head>
    <meta charset="utf-8">
    <script async src="https://cdn.ampproject.org/v0.js"></script>
    <script async custom-element="amp-story"
        src="https://cdn.ampproject.org/v0/amp-story-1.0.js"></script>
    <title>Hello, amp-story</title>
    <link rel="canonical" href="http://example.ampproject.org/my-story.html" />
    <meta name="viewport"
        content="width=device-width,minimum-scale=1,initial-scale=1">
    <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
  </head>
  <body>
    <amp-story standalone>
      <amp-story-page id="my-first-page">
        <amp-story-grid-layer template="fill">
          <amp-img src="https://example.ampproject.org/helloworld/bg1.jpg"
              width="900" height="1600">
          </amp-img>
        </amp-story-grid-layer>
        <amp-story-grid-layer template="vertical">
          <h1>Hello, amp-story!</h1>
        </amp-story-grid-layer>
      </amp-story-page>
      <amp-story-page id="my-second-page">
        <amp-story-grid-layer template="fill">
          <amp-img src="https://example.ampproject.org/helloworld/bg2.gif"
              width="900" height="1600">
          </amp-img>
        </amp-story-grid-layer>
        <amp-story-grid-layer template="vertical">
          <h1>The End</h1>
        </amp-story-grid-layer>
      </amp-story-page>
      <amp-story-bookend src="bookendv1.json" layout="nodisplay">
      </amp-story-bookend>
    </amp-story>
  </body>
</html>

The content in the body creates a story with two pages. Each page has a full bleed background image, with a simple string of text on top of it.

Required markup for amp-story

The AMP story HTML format follows the same markup requirements as a valid AMP HTML document, along with the following additional requirements:

RULE DESCRIPTION
The <amp-story standalone> element is the only child element of <body>. Identifies that the document is an AMP story.
Contain a <script async src="https://cdn.ampproject.org/v0/amp-story-1.0.js" custom-element="amp-story"></script> tag as the third child of the <head> tag. Includes and loads the amp-story JS library.
Contain a <link rel="canonical" href="$STORY_URL"> tag inside the <head>. The link points to the story itself, identifying the story as the canonical document.

Story: amp-story

The amp-story component represents an entire story. The component itself implements the UI shell, including handling gestures and navigation, and inserting the application shell UI (controls, progress bar, etc).

amp-story example

Example

<amp-story
    standalone
    title="My Story"
    publisher="The AMP Team"
    publisher-logo-src="https://example.com/logo/1x1.png"
    poster-portrait-src="https://example.com/my-story/poster/3x4.jpg"
    poster-square-src="https://example.com/my-story/poster/1x1.jpg"
    poster-landscape-src="https://example.com/my-story/poster/4x3.jpg"
    background-audio="my.mp3">
  <amp-story-page>[...]</amp-story-page>
  <amp-story-page>[...]</amp-story-page>
  <amp-story-page>[...]</amp-story-page>
  <amp-story-bookend src="./related.json"></amp-story-bookend>
</amp-story>

Attributes

standalone [required]

Identifies that the AMP document is a story.

title [required]

The title of the story.

publisher [required]

The name of the story's publisher.

publisher-logo-src [required]

A URL to the story publisher's logo in square format (1x1 aspect ratio). For example publisher-logo-src="https://example.com/logo/1x1.png", where 1x1.png is a 36x36 px logo.

poster-portrait-src [required]

A URL to the story poster in portrait format (3x4 aspect ratio).

supports-landscape [optional]

Enables landscape orientation support on mobile devices and a full bleed landscape experience on desktop devices.

background-audio [optional]

A URL to an audio file that plays throughout the story.

poster-square-src [optional]

A URL to the story poster in square format (1x1 aspect ratio).

poster-landscape-src [optional]

A URL to the story poster in landscape format (4x3 aspect ratio).

Posters

A "poster" is an image that displays in the UI until your story is loaded. The poster can generally be the first screen of your story, although you can use any image that is representative of the story.

Landscape orientation and full bleed desktop experience opt in

If the supports-landscape attribute is specified on the <amp-story> element, it will:

  • Allow the story to be seen when a mobile device is held in a landscape orientation.
  • Change the desktop experience to an immersive full bleed mode, replacing the default three portrait panels experience.

Usage: <amp-story ... supports-landscape>...</amp-story>

Before:

After:

Children (of amp-story)

The <amp-story> component contains one or more <amp-story-page> components, containing each of the individual screens of the story. The first page specified in the document order is the first page shown in the story.

Pages: amp-story-page

The <amp-story-page> component represents the content to display on a single page of a story.

Page 1 example

Page 2 example

Example

<amp-story-page id="cover">
  <amp-story-grid-layer template="fill">
    <amp-video layout="fill" src="background.mp4" poster="background.png" muted autoplay></amp-video>
  </amp-story-grid-layer>
  <amp-story-grid-layer template="vertical">
    <h1>These are the Top 5 World's Most...</h1>
    <p>Jon Bersch</p>
    <p>May 18</p>
  </amp-story-grid-layer>
  <amp-story-grid-layer template="thirds">
    <amp-img grid-area="bottom-third" src="a-logo.svg" width="64" height="64"></amp-img>
  </amp-story-grid-layer>
</amp-story-page>

Attributes

id [required]

A unique identifier for the page. Can be used for styling the page and its descendants in CSS, and is also used to uniquely identify the page in the URL fragment.

auto-advance-after [optional]

Specifies when to auto-advance to the next page. If omitted, the page will not automatically advance. The value for auto-advance-after must be either:

  • A positive amount of time to wait before automatically advancing to the next page
  • An ID of an HTMLMediaElement or video-interface video whose completion will trigger the auto-advance

For example:

<amp-story-page id="tokyo" auto-advance-after="1s">
background-audio [optional]

A URI to an audio file that plays while this page is in view.

For example:

<amp-story-page id="zurich" background-audio="./media/switzerland.mp3">

Children (of amp-story-page)

The <amp-story-page> component contains one or more layers. Layers are stacked bottom-up (the first layer specified in the DOM is at the bottom; the last layer specified in the DOM is at the top).

Layers

Layers are stacked on top of one another to create the desired visual effect.

amp-story-grid-layer

The <amp-story-grid-layer> component lays its children out into a grid. Its implementation is based off of the CSS Grid Spec.

+ + =

Attributes

template [required]

The template attribute determines the layout of the grid layer. Available templates are described in the Templates section below.

grid-area [optional]

This attribute is specified on children of <amp-story-grid-layer>. grid-area specifies the named area (from using a template that defines them) in which the element containing this attribute should appear.

Example:

<amp-story-grid-layer template="thirds">
  <p grid-area="middle-third">Element 1</p>
  <p grid-area="lower-third">Element 2</p>
  <p grid-area="upper-third">Element 3</p>
</amp-story-grid-layer>

Templates

The following are available templates to specify for the layout of the grid layer.

{% call callout('Tip', type='success') %} To see the layout templates in use, check out the layouts demo on AMP By Example. {% endcall %}

fill

The fill template shows its first child full bleed. All other children are not shown.

Names Areas: (none)

Example:

Horizontal template example

<amp-story-grid-layer template="fill">
  <amp-img src="cat.jpg"></amp-img>
</amp-story-grid-layer>
vertical

The vertical template lays its elements out along the y-axis. By default, its elements are aligned to the top, and can take up the entirety of the screen along the x-axis.

Names Areas: (none)

Horizontal template example

<amp-story-grid-layer template="vertical">
  <p>Element 1</p>
  <p>Element 2</p>
  <p>Element 3</p>
</amp-story-grid-layer>
horizontal

The horizontal template lays its elements out along the x-axis. By default, its elements are aligned to the start of the line and can take up the entirety of the screen along the y-axis.

Names Areas: (none)

Horizontal template example

<amp-story-grid-layer template="horizontal">
  <p>Element 1</p>
  <p>Element 2</p>
  <p>Element 3</p>
</amp-story-grid-layer>
thirds

The thirds template divides the screen into three equally-sized rows, and allows you to slot content into each area.

Named Areas:

  • upper-third
  • middle-third
  • lower-third

Thirds template example

<amp-story-grid-layer template="thirds">
  <p grid-area="middle-third">Element 1</p>
  <p grid-area="lower-third">Element 2</p>
  <p grid-area="upper-third">Element 3</p>
</amp-story-grid-layer>

Children

An amp-story-grid-layer can contain any of the following elements:

Note: This list will be expanded over time.

Area Allowable tags
Media
  • <amp-audio>
  • <amp-gfycat>
  • <amp-google-vrview-image>
  • <amp-img>
  • <amp-video>
  • <source>
  • <track>
Analytics & Measurement
  • <amp-analytics>
  • <amp-experiment>
  • <amp-pixel>
Sectioning
  • <address>
  • <article>
  • <aside>
  • <footer>
  • <h1>-<h6>
  • <header>
  • <hgroup>
  • <nav>
  • <section>
  • <amp-story-cta-layer>
Text
  • <abbr>
  • <amp-fit-text>
  • <amp-font>
  • <amp-gist>
  • <b>
  • <bdi>
  • <bdo>
  • <blockquote>
  • <br>
  • <cite>
  • <code>
  • <data>
  • <del>
  • <dfn>
  • <div>
  • <em>
  • <figcaption>
  • <figure>
  • <hr>
  • <i>
  • <ins>
  • <kbd>
  • <main>
  • <mark>
  • <p>
  • <pre>
  • <q>
  • <rp>
  • <rt>
  • <rtc>
  • <ruby>
  • <s>
  • <samp>
  • <small>
  • <span>
  • <strong>
  • <sub>
  • <sup>
  • <time>
  • <u>
  • <var>
  • <wbr>
Lists
  • <amp-list>
  • <amp-live-list>
  • <dd>
  • <dl>
  • <dt>
  • <li>
  • <ol>
  • <ul>
Tables
  • <caption>
  • <col>
  • <colgroup>
  • <table>
  • <tbody>
  • <td>
  • <tfoot>
  • <th>
  • <thead>
  • <tr>
Links
  • <a>
Other
  • <amp-install-serviceworker>
  • <noscript>

Links in amp-story-grid-layer

We support inline links <a> as a descendant of amp-story-grid-layer. Whenever a link is tapped a tooltip will be shown - deferring the corresponding action until the user taps again in the tooltip.

Customizing tooltip for links

You can customize the contents of the tooltip displayed on top of a user interactive element by specifying the following attributes. If they are not specified, a fallback value will be provided automatically.

Example:

data-tooltip-icon

Takes in a src where the icon image is located.

data-tooltip-text

A string that will be shown when the tooltip appears.

Example:

<a href="https://www.google.com" role="link" data-tooltip-icon="./assets/ic_amp_googblue_1x_web_24dp.png" data-tooltip-text="Go to page">
  Click me!
</a>

amp-story-cta-layer

The <amp-story-cta-layer> component allows the usage of <a> and <button> elements inside an <amp-story-page>.

Constraints

  • If specified, the <amp-story-cta-layer> element must be the last layer within an <amp-story-page>. As a result, effectively every <amp-story-page> can have exactly one or exactly zero of the <amp-story-cta-layer> element.
  • Positioning and sizing of this layer cannot be controlled. It is always 100% width of the page, 20% height of the page, and aligned to the bottom of the page.

Example

<amp-story-page id="vertical-template-thirds">
  <amp-story-grid-layer template="thirds">
    <div class="content" grid-area="upper-third">Paragraph 1</div>
    <div class="content" grid-area="middle-third">Paragraph 2</div>
    <div class="content" grid-area="lower-third">Paragraph 3</div>
  </amp-story-grid-layer>
  <amp-story-cta-layer>
    <a href="https://www.ampproject.org" class="button">Outlink here!</a>
  </amp-story-cta-layer>
</amp-story-page>

Complete example found in the examples directory

Children

The amp-story-cta-layer allows mostly the same descendants as amp-story-grid-layer, and additionally allows <a> and <button> tags.

For an updated list of supported children, be sure to take a look at the amp-story-cta-layer-allowed-descendants field in the validation rules.

Page attachments

amp-story-page-attachment

AMP Story page attachment

Attach additional content to a story page!

Story page attachments allow you to provide additional AMPHTML content to specific pages. This content can be revealed by users through a "swipe up" gesture, or a tap on the call to action element. A UI prompt to open the attachment will automatically be added at the bottom of every page that configured an attachment.

The <amp-story-page-attachment> element must be the last child of <amp-story-page>, and must have the layout="nodisplay" attribute. The attachment AMPHTML content is expected to be provided inline in your AMP Story, within this <amp-story-page-attachment> tag.

Allowed content and components

Story page attachments allow the same HTML elements as AMP Story along with additional components listed below, such as third party video players or social media embeds. This means you can add additional content that is too verbose or disallowed in an AMP Story page.

List of allowed AMP components in a page attachment
  • <amp-3d-gltf>
  • <amp-3q-player>
  • <amp-accordion>
  • <amp-audio>
  • <amp-beopinion>
  • <amp-bodymovin-animation>
  • <amp-brid-player>
  • <amp-brightcove>
  • <amp-byside-content>
  • <amp-call-tracking>
  • <amp-carousel>
  • <amp-dailymotion>
  • <amp-date-countdown>
  • <amp-embedly-card>
  • <amp-facebook>
  • <amp-facebook-comments>
  • <amp-facebook-like>
  • <amp-facebook-page>
  • <amp-fit-text>
  • <amp-fx-collection>
  • <amp-fx-flying-carpet>
  • <amp-gfycat>
  • <amp-gfycat>
  • <amp-gist>
  • <amp-gist>
  • <amp-google-document-embed>
  • <amp-google-vrview-image>
  • <amp-google-vrview-image>
  • <amp-hulu>
  • <amp-ima-video>
  • <amp-image-slider>
  • <amp-img>
  • <amp-imgur>
  • <amp-instagram>
  • <amp-izlesene>
  • <amp-jwplayer>
  • <amp-kaltura-player>
  • <amp-list>
  • <amp-list>
  • <amp-live-list>
  • <amp-live-list>
  • <amp-mathml>
  • <amp-mowplayer>
  • <amp-nexxtv-player>
  • <amp-o2-player>
  • <amp-ooyala-player>
  • <amp-pan-zoom>
  • <amp-pinterest>
  • <amp-playbuzz>
  • <amp-powr-player>
  • <amp-reach-player>
  • <amp-reddit>
  • <amp-riddle-quiz>
  • <amp-soundcloud>
  • <amp-springboard-player>
  • <amp-timeago>
  • <amp-twitter>
  • <amp-video>
  • <amp-video-iframe>
  • <amp-vimeo>
  • <amp-vine>
  • <amp-viqeo-player>
  • <amp-vk>
  • <amp-wistia-player>
  • <amp-yotpo>
  • <amp-youtube>

Example

<amp-story-page id="foo">
  <amp-story-grid-layer template="fill">
    <amp-img src="https://example.ampproject.org/helloworld/bg1.jpg" width="900" height="1600">
  </amp-story-grid-layer>
  <amp-story-page-attachment layout="nodisplay">
    <h1>My title</h1>
    <p>Lots of interesting text with <a href="https://example.ampproject.org">links</a>!</p>
    <p>More text and a YouTube video!</p>
    <amp-youtube
        data-videoid="b4Vhdr8jtx0"
        layout="responsive"
        width="480" height="270">
    </amp-youtube>
    <p>And a tweet!</p>
    <amp-twitter
        data-tweetid="885634330868850689"
        layout="responsive"
        width="480" height="270">
    </amp-twitter>
  </amp-story-page-attachment>
</amp-story-page>

Animations

Every element inside an <amp-story-page> can have an entrance animation.

You can configure animations by specifying a set of animation attributes on the element; no additional AMP extensions or configuration is needed.

Animation effects

The following animation effects are available as presets for AMP stories:

Preset name Default duration (ms) Default delay (ms)
drop 1600 0
fade-in 500 0
fly-in-bottom 500 0
fly-in-left 500 0
fly-in-right 500 0
fly-in-top 500 0
pulse 500 0
rotate-in-left 700 0
rotate-in-right 700 0
twirl-in 1000 0
whoosh-in-left 500 0
whoosh-in-right 500 0
pan-left 1000 0
pan-right 1000 0
pan-down 1000 0
pan-up 1000 0
zoom-in 1000 0
zoom-out 1000 0

{% call callout('Tip', type='success') %} See a live demo of all the AMP story animations on AMP By Example. {% endcall %}

Animation attributes

animate-in [required]

Use this attribute to specify the name of the entrance animation preset.

Example: A heading flies in from left of the page.

<h2 animate-in="fly-in-left">
Fly from left!
</h2>
animate-in-duration [optional]

Use this attribute to specify the duration of the entrance animation, in seconds or milliseconds (e.g., 0.2s or 200ms). The default duration depends on the animation preset you specified.

Example: A heading flies in from left of the page and the animation finishes within half a second.

<h2 animate-in="fly-in-left" animate-in-duration="0.5s" >
Fly from left!
</h2>
animate-in-delay [optional]

Use this attribute to specify the delay before starting the animation. The value must be greater than or equal to 0, in seconds or milliseconds (for example, 0.2s or 200ms). The default delay depends on the animation preset you specified.

Example: After 0.4 seconds, a heading flies in from the left of the page and completes its entrance within 0.5 seconds.

<h2 animate-in="fly-in-left"
    animate-in-duration="0.5s"
    animate-in-delay="0.4s">
Fly from left!
</h2>

{% call callout('Note', type='note') %} The animation delay is not guaranteed to be exact. Additional delays can be caused by loading the amp-animation extension in the background when the first animated element has been scanned. The attribute contract is defined as delay this animation for at least N milliseconds. This applies to all elements including those with a delay of 0 seconds. {% endcall %}

animate-in-after [optional]

Use this attribute to chain or sequence animations (for example, animation2 starts after animation1 is complete). Specify the ID of the animated element that this element's animation will follow. The element must be present on the same <amp-story-page>. The delay is applied after the previous element's animation has finished. For further details, see the Sequencing animations section below.

For example, in the following code, object2 animates in after object1 completes their entrance:

<amp-story-page id="page1">
  <amp-story-grid-layer template="vertical">
    <div id="object1"
        animate-in="rotate-in-left">
        1
    </div>
    <div id="object2"
        animate-in="fly-in-right"
        animate-in-after="object1">
        2 <!-- will start after object1 has finished -->
    </div>
  </amp-story-grid-layer>
</amp-story-page>
scale-start, scale-end [optional, only works with zoom-in & zoom-out animations]

Use these two attributes to further specify the parameters of your zoom-in and zoom-out animations. The value must be greater than or equal to 0, and decimals are allowed. The default will be scale-start: 1 and scale-start: 3 for zoom-in, and the inverse for zoom-out.

Example: An image zooming-in from 2x to 5x its size over 4 seconds.

<amp-img animate-in="zoom-in" scale-start="2" scale-end="5" animate-in-duration="4s" layout="fixed" src="https://picsum.photos/720/320?image=1026" width="720" height="320">
</amp-img>
translate-x [optional, only works with pan-left & pan-right animations]

Use this attribute to specify the horizontal panning of your image in a pan-left/pan-right animation. The value must be greater than or equal to 0 in pixels. The default value will pan the whole width of the specified image.

Example: An image panning 200px to the left over 10 seconds.

<amp-img animate-in="pan-left" translate-x="200px" animate-in-duration="10s" layout="fixed" src="https://picsum.photos/720/320?image=1026" width="720" height="320">
</amp-img>
translate-y [optional, only works with pan-up & pan-down animations]

Use this attribute to specify the vertical panning of your image in a pan-up/pan-down animation. The value must be greater than or equal to 0 in pixels. The default value will pan the whole height of the specified image.

Example: An image panning 50px down over 15 seconds.

<amp-img animate-in="pan-down" translate-y="50px" animate-in-duration="15s" layout="fixed" src="https://picsum.photos/720/320?image=1026" width="720" height="320">
</amp-img>

Sequencing animations

To chain animations in sequence, use the animate-in-after attribute. All elements in a given chain must be present in the same <amp-story-page>. Elements without the animate-in-after attribute do not belong to a sequence chain, and will start independently on page entrance.

<amp-story-page id="my-sequencing-page">
  <amp-story-grid-layer template="vertical">
    <div class="circle"
        animate-in="drop-in"
        animate-in-duration="1.8s">
      1 <!-- will start independently -->
    </div>
    <div id="rotate-in-left-obj"
        class="square"
        animate-in="rotate-in-left"
        animate-in-after="fade-in-obj"
        animate-in-delay="0.2s">
      2 <!-- will start after fade-in-obj has finished -->
    </div>
    <div class="square"
        animate-in-after="rotate-in-left-obj"
        animate-in="whoosh-in-right"
        animate-in-delay="0.2s">
      3 <!-- will start after rotate-in-left-obj has finished -->
    </div>
    <div id="fade-in-obj"
        class="circle"
        animate-in="fade-in"
        animate-in-duration="2.2s">
      1 <!-- will start independently -->
    </div>
  </amp-story-grid-layer>
</amp-story-page>

Combining multiple animations

You can apply multiple entrance animations on one element (for example, an element flies into the page and fades in at the same time). It's not possible to assign more than one animation preset to a single element; however, elements with different entrance animations can be nested to combine them into one.

<div animate-in="fly-in-left">
   <div animate-in="fade-in">
     I will fly-in and fade-in!
   </div>
</div>

{% call callout('Note', type='note') %} If a composed animation is supposed to start after the end of a separate element's animation, make sure that all nested elements that compose the animation have the attribute animate-in-after set to the same id. {% endcall %}

Bookend: amp-story-bookend

The amp-story-bookend is the last screen of the story. It contains related links, sharing options, call to action links, and more.

related article example

To use it, include an <amp-story-bookend> tag as the child of your <amp-story> with the required attribute layout=nodisplay. You can then specify the JSON configuration in a separate file and import it through the src attribute, or you can place it inline.

Importing the JSON configuration through the src attribute:

<amp-story standalone>
  <amp-story-page id="cover">
    ...
  </amp-story-page>
  <!-- `layout=nodisplay` is required. -->
  <amp-story-bookend src="bookendv1.json" layout=nodisplay>
  </amp-story-bookend>
<amp-story>

If you don't want to fetch the bookend configuration from a server, you can also specify it inline:

<amp-story standalone>
  ...
  <amp-story-bookend layout=nodisplay>
    <script type="application/json">
      {
        "bookendVersion": "v1.0",
        "shareProviders": [ ... ],
        "components": [ ... ]
     }
    </script>
  </amp-story-bookend>
<amp-story>

Next, you must fill in the JSON configuration. This is where you customize the bookend. The overall structure of the config looks like so:

{
  "bookendVersion": "v1.0",
  "shareProviders": [
    ...
  ],
  "components": [
    ...
  ]
}

It is required to specify you are using the v1.0 version by including the first line.

Bookend components

The bookend is made up of a variety of components. These components can be articles, call to action links, text, and more.

They are specified in the components field of the configured JSON. See the Example JSON response section below for an example.

heading

The heading component has a text field, which can be used to append a title to a group of articles.

{
  "type": "heading",
  "text": "More to Read"
}

Bookend heading component

small

The small component can be used to link to related articles. This component requires the following fields: title, url, and optionally an image.

{
  "type": "small",
  "title": "This is India an the best places you should go",
  "url": "http://example.com/article.html",
  "image": "http://placehold.it/256x128"
}

Bookend small component

landscape

The landscape component can be used for alternative formats of content, like videos. This component requires the following fields: title, url, and image. Optionally, you can add a category field, which displays a subheading above the title.

{
  "type": "landscape",
  "title": "TRAPPIST-1 Planets May Still Be Wet Enough for Life",
  "url": "http://example.com/article.html",
  "category": "astronomy",
  "image": "http://placehold.it/256x128"
}

Bookend landscape component

portrait

The portrait component can be used to link to other stories. This component requires the following fields: title, url, and image. Optionally, you can add a category field, which displays a subheading above the title.

{
  "type": "portrait",
  "category": "Science",
  "title": "New discovery found",
  "url": "http://example.com/article.html",
  "image": "http://placehold.it/312x416"
}

Bookend portrait component

cta-link

The cta-link component lets you specify links for call to actions (e.g., Read More or Subscribe). This component has a links key, which specifies an array of links. Each link is an object with a text and url values.

{
  "type": "cta-link",
  "links": [
    {
      "text": "Sign Up",
      "url": "example.com/signup"
    },
    {
      "text": "Subscribe",
      "url": "example.com/subscribe"
    }
  ]
}

Bookend cta-links component

textbox

The textbox component lets you specify text inside the bookend (for example, photo credits). This component requires a text array, where each element of the array is a line of text.

{
  "type": "textbox",
  "text": [
    "Food by Enrique McPizza",
    "Choreography by Gabriel Filly",
    "Script by Alan Ecma S.",
    "Direction by Jon Tarantino"
  ]
}

Bookend textbox component

AMP-to-AMP linking

For documents displayed in an AMP viewer, links typically navigate _top or open in a new window. Links to AMP pages, however, may continue to be displayed in the viewer. To enable this behavior, add "amphtml": true to a component that supports links. For example:

...
{
  "type": "small",
  "title": "This is India an the best places you should go",
  "url": "http://example.com/my-amp-document.html",
  "image": "http://placehold.it/256x128",
  "amphtml": true
},
{
  "type": "cta-link",
  "links": [
    {
      "text": "Sign Up",
      "url": "example.com/signup",
      "amphtml": true
    },
    {
      "text": "Subscribe",
      "url": "example.com/subscribe"
    }
  ]
},
...

Social sharing

The configuration for social sharing is defined in the shareProviders field of the response object, and it's optional.

This field should contain a string, where each string respresents a share provider's name (e.g. twitter).

When extra parameters are required, an object with key-value pairs should be used. The object should contain a key provider with a value (e.g. facebook) corresponding to the provider's name. The next key-values will depend on the share provider.

The list of available providers is the same as in the amp-social-share component.

Each of these providers has a different set of available parameters (see data-param-*). The configuration object takes these parameters without the data-param- prefix (for example, the data-param-app_id would appear in the configuration object as app_id).

JSON configuration

The <amp-story-bookend> must have a src attribute pointing to the JSON configuration of the bookend. It is described as a URL endpoint that accepts GET requests and returns a JSON response with the contents of the bookend. If omitted, the amp-story component renders a default UI for the end screen. The system is responsible for fetching the data necessary to render related and trending articles. This can be served from a static JSON file, or dynamically-generated (e.g., to calculate what is currently trending).

Example JSON response

{
  // You must specify version v1.0.
  "bookendVersion": "v1.0",
  "shareProviders": [
    "email",
    "tumblr",
    {
      "provider": "twitter",
      // You can add custom sharing parameters depending on the social platform.
      "text": "This is custom share text that I would like for the Twitter platform"
    },
    {
      "provider": "facebook",
      // Facebook requires an `app_id` param
      "app_id": "MY_FACEBOOK_APP_ID"
    }
  ],
  "components": [
    {
      "type": "heading",
      "text": "More to read"
    },
    {
      "type": "small",
      "title": "This is India an the best places you should go",
      "url": "http://example.com/article.html",
      "image": "http://placehold.it/256x128"
    },
    ...
  ]
}

Experimental Feature: Branching

Branching is a set of experimental features that allow the construction of non-linear stories. By utilizing these features, you can create stories that start from somewhere other than the beginning, share specific pages of stories, or even allow users to jump around within a story. Example use cases include quizzes, choose-your-own-story experiences, and story table of contents.

All branching features are behind an amp-story-branching experiment. To turn on the experiment, enable it in your dev console:

AMP.toggleExperiment('amp-story-branching')

For more information see, experimental features.

Manipulating Navigation

The features listed below allow you to manipulate navigation within a story. When using branching features, navigation throughout the story from a 'branch-off point' will follow the path that a user takes. That is, if a user navigates from page-1 to page-5 and then page-6, navigating backwards will follow this exact path (page-6 to page-5 and finally page-1). The other pages will not be exposed to the user.

goToPage action

The goToPage action allows for 'jumping' from one page within a story to another. The action can be used with allowed elements in amp-story and their respective events. Clicking on an element with this action should bring the user to another page within the same story. Using this action requires that you give the amp-story element an id, a unique identifier, as the story itself is the target. Read more about actions and events in AMP here.

Action Description
goToPage(id=STRING) Navigates to a target page. Id refers to the required page id

The following example shows a story with a quiz experience. The first page acts as a branch off point that allows the user to select the path that the story takes.

<amp-story id="story" standalone>
    <amp-story-page id="cover">
        <amp-story-grid-layer>
        <p> What is your favourite food? </p>
          <button on="tap:story.goToPage(id=bacon-answer)"> Bacon! </button>
          <button on="tap:story.goToPage(id=boba-answer)"> Boba! </button>
          <button on="tap:story.goToPage(id=pizza-answer)"> Pizza! </button>
        </amp-story-grid-layer>
    </amp-story-page>

    <amp-story-page id="bacon-answer">
        <amp-story-grid-layer>
          <p> Bacon, of course! </p>
        </amp-story-grid-layer>
    </amp-story-page>

    <amp-story-page id="boba-answer">
        <amp-story-grid-layer>
          <p> Boba, because it's a perfect drink! </p>
        </amp-story-grid-layer>
    </amp-story-page>

    <amp-story-page id="pizza-answer">
        <amp-story-grid-layer>
        <p> Pizza, it's a true classic! </p>
        </amp-story-grid-layer>
    </amp-story-page>
    ...
</amp-story>

advance-to attribute

The advance-to attribute specifies which page should follow a given amp-story-page as the user advances through the story. Without branching, the following page defaults to the next amp-story-page in the DOM. This will still be the default behavior if you choose to not specify the advance-to attribute when creating non-linear stories.

Attribute Description
advance-to Specifies what page should follow when the user advances next. The id of the page that should follow is required.

The following is a modification of the previous story with a quiz experience. By using the advance-to attribute, we create a fallback page to navigate to should the user not select any of the food items listed.

<amp-story id="story" standalone>
    <amp-story-page id="cover" advance-to="fallback-answer">
        <amp-story-grid-layer>
          <p> What is your favourite food? </p>
          <button on="tap:story.goToPage(id=bacon-answer)"> Bacon! </button>
          <button on="tap:story.goToPage(id=boba-answer)"> Boba! </button>
          <button on="tap:story.goToPage(id=pizza-answer)"> Pizza! </button>
        </amp-story-grid-layer>
    </amp-story-page>

    <amp-story-page id="bacon-answer">
        <amp-story-grid-layer>
          <p> Bacon, of course! </p>
        </amp-story-grid-layer>
    </amp-story-page>

    <amp-story-page id="boba-answer">
        <amp-story-grid-layer>
        <p> Boba, because it's a perfect drink! </p>
        </amp-story-grid-layer>
    </amp-story-page>

    <amp-story-page id="pizza-answer">
        <amp-story-grid-layer>
          <p> Pizza, it's a true classic! </p>
        </th>amp-story-grid-layer>
    </amp-story-page>

    <amp-story-page id="fallback-answer">
        <amp-story-grid-layer>
          <p> It looks like you like something else. You're very unique! </p>
        </amp-story-grid-layer>
    </amp-story-page>
    ...
</amp-story>

If the advance-to attribute had not been used with the fallback-answer value and the user advanced forward without selecting a choice, the story would have presented the the bacon-answer page.

Sharing Options

We've added support for creating and sharing URLs to specific pages within the story.

URL Fragment Parameter

With branching, AMP Stories now supports URLs in the form of:

https://www.mydomain.com/good-story/#page=<page-id>

where page-id refers to the unique id of an amp-story-page. You can also use the fragment parameter and the page-id value like an anchor link in some use cases. See Integration with Sidebar for Stories for an example.

Sharing a Specific Story Page

With branching turned on, users will have the option to share the story from the page they are currently seeing. If a user selects the option to share from the page they are currently seeing, the URL generated will be in the form described above. Important, branching may expose the amp-story-page ids to the user.

Integration with Sidebar for Stories

The use of amp-sidebar is supported for use within amp-story. See the Sidebar for Stories documentation for information on limitations and caveats.

By using both branching features and amp-sidebar, you can create stories that have a table of contents. To do this, make use of the goToPage action and URL fragment parameter.

The following is a modification of the previous story with a quiz experience. We add an amp-sidebar that has in it both a table of contents and out-links to other links of interest. While there are two valid ways to link to pages within the story within a sidebar, we recommend using the goToPage action.

<amp-story id="story" standalone>
    <amp-sidebar id="sidebar1" layout="nodisplay">
            <ul>
                <li on="tap:story.goToPage(id=cover)"> Cover Page </li>
                <li> <a href="#page=bacon-answer"> Bacon page </a></li>
                <li> <a href="https://www.amp.dev"> External Link </a></li>
            </ul>
     </amp-sidebar>

    <amp-story-page id="cover" advance-to="fallback-answer">
        <amp-story-grid-layer>
          <p> What is your favourite food? </p>
          <button on="tap:story.goToPage(id=bacon-answer)"> Bacon! </button>
          <button on="tap:story.goToPage(id=boba-answer)"> Boba! </button>
          <button on="tap:story.goToPage(id=pizza-answer)"> Pizza! </button>
        </amp-story-grid-layer>
    </amp-story-page>

    <amp-story-page id="bacon-answer">
        <amp-story-grid-layer>
          <p> Bacon, of course! </p>
        </amp-story-grid-layer>
    </amp-story-page>
    ...
</amp-story>

Other components usable in AMP stories

The following are other components usable in AMP stories that require some story-specific caveats.

For more generally usable components see the list of allowed children.

Validation

See amp-story rules in the AMP validator specification.

Localization

To localize your story, include the language code in the lang attribute on the <html> tag of your story, such as <html ⚡ lang="en"> for English. The supported language codes are:

  • ar (Arabic)
  • de (German)
  • en-GB (English, UK)
  • en (English, US)
  • es-419 (Spanish, Central/Latin America)
  • es (Spanish, Spain)
  • fr-CA (French, Canada)
  • fr (French, France)
  • hi (Hindi)
  • id (Indonesian)
  • it (Italian)
  • ja (Japanese)
  • ko (Korean)
  • nl (Dutch)
  • no (Norwegian)
  • pt-BR (Portuguese, Brazil)
  • pt (Portuguese, Portugal)
  • ru (Russian)
  • tr (Turkish)
  • vi (Vietnamese)
  • zh-TW (Traditional Chinese)
  • zh (Simplified Chinese)

Additionally, for right-to-left languages, you may include the dir="rtl" attribute on the <html> tag of your story. This may be used in conjunction with the language code as well, e.g. <html ⚡ lang="ar" dir="rtl">.

Related resources