AMP
  • websites

Image Galleries with amp-carousel

Introduction

The amp-carousel component works great for image galleries. The carousel requires the height attribute to be specified in advance. This can be tricky if the displayed images and captions vary in size. Here are two approaches to solve this problem.

Setup

Import the carousel component in the header.

<script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>

We will be using the amp-fit-text component to fit captions to the available space.

<script async custom-element="amp-fit-text" src="https://cdn.ampproject.org/v0/amp-fit-text-0.1.js"></script>

Carousel previews can be implemented with amp-selector component.

<script async custom-element="amp-selector" src="https://cdn.ampproject.org/v0/amp-selector-0.1.js"></script>

We sync the carousel state using the amp-bind component.

<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>

The amp-lightbox-gallery component allows us to quickly create a lightbox gallery.

<script async custom-element="amp-lightbox-gallery" src="https://cdn.ampproject.org/v0/amp-lightbox-gallery-0.1.js"></script>

Captions with dynamic text size

The first image gallery uses amp-fit-text to fit the text to the available space. This works well if captions vary not too much in length.

The Border Collie is a working and herding dog breed developed in the Anglo-Scottish border region for herding livestock, especially sheep. It was specifically bred for intelligence and obedience. Considered highly intelligent, and typically extremely energetic, acrobatic, smart and athletic, they frequently compete with great success in dog sports, in addition to their success in sheepdog trials. They are often cited as the most intelligent of all domestic dogs. Border Collies also remain employed throughout the world in their traditional work of herding livestock.
The Shetland Sheepdog, often known as the Sheltie, is a breed of herding dog. Less favored nicknames are the Toy Collie and the Miniature Collie. They are small dogs, and come in a variety of colors, such as sable, tri-color, and blue merle. They are very intelligent, vocal, excitable, energetic dogs who are always willing to please and work hard.
The Hovawart is a medium to large size German dog breed. The name of the breed means "an estate guard dog", which is the original use for the breed. The breed originated in the Black Forest region and was first described in text and paintings in medieval times.
<amp-carousel class="carousel1"
  layout="responsive"
  height="450"
  width="500"
  type="slides">
  <div class="slide">
    <amp-img src="/static/samples/img/Border_Collie.jpg"
      layout="responsive"
      width="500"
      height="300"
      alt="Border Collie"></amp-img>
    <amp-fit-text layout="responsive"
      width="500"
      height="150"> The Border Collie is a working and herding dog breed developed in the Anglo-Scottish border region for herding livestock, especially sheep. It was specifically bred for intelligence and obedience. Considered highly intelligent, and typically extremely energetic, acrobatic, smart and athletic, they frequently compete with great success in dog sports, in addition to their success in sheepdog trials. They are often cited as the most intelligent of all domestic dogs. Border Collies also remain employed throughout the world in their traditional work of herding livestock. </amp-fit-text>
  </div>

  <div class="slide">
    <amp-img src="/static/samples/img/Shetland_Sheepdog.jpg"
      layout="responsive"
      width="500"
      height="340"
      alt="Shetland Sheepdog"></amp-img>
    <amp-fit-text layout="responsive"
      width="500"
      height="110"> The Shetland Sheepdog, often known as the Sheltie, is a breed of herding dog. Less favored nicknames are the Toy Collie and the Miniature Collie. They are small dogs, and come in a variety of colors, such as sable, tri-color, and blue merle. They are very intelligent, vocal, excitable, energetic dogs who are always willing to please and work hard.
    </amp-fit-text>
  </div>

  <div class="slide">
    <amp-img src="/static/samples/img/Hovawart.jpg"
      layout="responsive"
      width="500"
      height="350"
      alt="Hovawart"></amp-img>
    <amp-fit-text layout="responsive"
      width="500"
      height="100">
      The Hovawart is a medium to large size German dog breed. The name of the breed means "an estate
      guard dog", which is the original use for the breed. The breed originated in the Black Forest
      region and was first described in text and paintings in medieval times.
    </amp-fit-text>
  </div>
</amp-carousel>

Caption with text overlay

Another carousel with caption, this time the caption overlays the image.

The Border Collie is a working and herding dog breed developed in the Anglo-Scottish border region for herding livestock, especially sheep. It was specifically bred for intelligence and obedience.
The Shetland Sheepdog, often known as the Sheltie, is a breed of herding dog. Less favored nicknames are the Toy Collie and the Miniature Collie. They are small dogs, and come in a variety of colors, such as sable, tri-color, and blue merle. They are very intelligent, vocal, excitable, energetic dogs who are always willing to please and work hard.
The Hovawart is a medium to large size German dog breed. The name of the breed means "an estate guard dog", which is the original use for the breed. The breed originated in the Black Forest region and was first described in text and paintings in medieval times.
<amp-carousel class="carousel2"
  layout="responsive"
  height="400"
  width="500"
  type="slides">
  <div class="slide">
    <amp-img src="/static/samples/img/Border_Collie.jpg"
      layout="fill"
      alt="Border Collie"></amp-img>
    <div class="caption">
      The Border Collie is a working and herding dog breed developed in the Anglo-Scottish border region
      for herding livestock, especially sheep. It was specifically bred for intelligence and obedience.
    </div>
  </div>

  <div class="slide">
    <amp-img src="/static/samples/img/Shetland_Sheepdog.jpg"
      layout="fill"
      alt="Shetland Sheepdog"></amp-img>
    <div class="caption">
      The Shetland Sheepdog, often known as the Sheltie, is a breed of herding dog. Less favored nicknames
      are the Toy Collie and the Miniature Collie. They are small dogs, and come in a variety of colors,
      such as sable, tri-color, and blue merle. They are very intelligent, vocal, excitable, energetic dogs
      who are always willing to please and work hard.
    </div>
  </div>

  <div class="slide">
    <amp-img src="/static/samples/img/Hovawart.jpg"
      layout="fill"
      alt="Hovawart"></amp-img>
    <div class="caption">
      The Hovawart is a medium to large size German dog breed. The name of the breed means "an estate guard
      dog", which is the original use for the breed. The breed originated in the Black Forest region and was
      first described in text and paintings in medieval times.
    </div>
  </div>
</amp-carousel>

Collapsible Image Captions with amp-bind

Here is another workaround for image captions: expandable captions. The idea is to first show only the first line of a caption (using text-overflow: ellipsis;). When the user clicks on the caption, the caption is expanded to show the full text. This works by using amp-bind to toggle a CSS class expanded when the caption is clicked.

This sample uses the trick described here to ensure that images never overlap the caption. A positive side-effect is that image dimensions don't need to be known in advance either. This makes it a very flexible approach for an image carousel with images and captions of unknown size/length.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.
<amp-carousel class="collapsible-captions"
  height="332"
  layout="fixed-height"
  type="slides">
  <figure>
    <div class="fixed-height-container">
      <amp-img layout="fill"
        src="https://unsplash.it/500/400"></amp-img>
    </div>
    <figcaption on="tap:AMP.setState({expanded: !expanded})"
      tabindex="0"
      role="button"
      [class]="expanded ? 'expanded' : ''">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.
      <span [text]="expanded ? '&#9660;' : '&#9650;'">&#9650;</span>
    </figcaption>
  </figure>
  <figure>
    <div class="fixed-height-container">
      <amp-img layout="fill"
        src="https://unsplash.it/500/500"></amp-img>
    </div>
    <figcaption on="tap:AMP.setState({expanded: !expanded})"
      tabindex="0"
      role="button"
      [class]="expanded ? 'expanded' : ''">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.
      <span [text]="expanded ? '&#9660;' : '&#9650;'">&#9650;</span></figcaption>
  </figure>
  <figure>
    <div class="fixed-height-container">
      <amp-img layout="fill"
        src="https://unsplash.it/200/500"></amp-img>
    </div>
    <figcaption on="tap:AMP.setState({expanded: !expanded})"
      tabindex="0"
      role="button"
      [class]="expanded ? 'expanded' : ''">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.
      <span [text]="expanded ? '&#9660;' : '&#9650;'">&#9650;</span></figcaption>
  </figure>
</amp-carousel>

Linking carousels with amp-bind

With amp-bind it's possible to link carousel state across multiple amp-carousels. Whenever the carousel slide changes, it updates selectedSlide. This causes the text attribute in the <p> tag above the carousel to update as well.

Only whitelisted functions are allowed when using amp-bind. We use the unary plus operator before selectedSlide to cast it into an integer.

Selected slide: 1/3

<div>
  <p>Selected slide: <span [text]="+selectedSlide + 1">1</span>/3</p>

  <amp-carousel controls
    type="slides"
    width="400"
    height="300"
    [slide]="selectedSlide"
    on="slideChange:AMP.setState({ selectedSlide: event.index })">
    <amp-img src="/static/samples/img/image1.jpg"
      layout="fill"></amp-img>
    <amp-img src="/static/samples/img/image2.jpg"
      layout="fill"></amp-img>
    <amp-img src="/static/samples/img/image3.jpg"
      layout="fill"></amp-img>
  </amp-carousel>
</div>

You can reveal specific slides in carousel using an on tap action on="tap:my-carousel.goToSlide(index=0)". Slides are identified by the carousel id and index (starting at 0).

<div>
  <amp-selector id="carouselWithPreviewSelector"
    class="carousel-preview"
    on="select:carouselWithPreview.goToSlide(index=event.targetOption)"
    layout="container">
    <amp-img option="0"
      selected
      src="https://unsplash.it/60/40?image=10"
      width="60"
      height="40"
      alt="a sample image"></amp-img>
    <amp-img option="1"
      src="https://unsplash.it/60/40?image=11"
      width="60"
      height="40"
      alt="a sample image"></amp-img>
    <amp-img option="2"
      src="https://unsplash.it/60/40?image=12"
      width="60"
      height="40"
      alt="a sample image"></amp-img>
    <amp-img option="3"
      src="https://unsplash.it/60/40?image=13"
      width="60"
      height="40"
      alt="a sample image"></amp-img>
  </amp-selector>
  <amp-carousel id="carouselWithPreview"
    width="400"
    height="300"
    layout="responsive"
    type="slides"
    on="slideChange:carouselWithPreviewSelector.toggle(index=event.index, value=true)">
    <amp-img src="https://unsplash.it/400/300?image=10"
      layout="fill"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=11"
      layout="fill"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=12"
      layout="fill"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=13"
      layout="fill"
      alt="a sample image"></amp-img>
  </amp-carousel>
</div>

You can even use a second carousel for the preview if a carousel contains a large number of images (make sure to use the type=carousel for the second one).

Both carousels sync the selected element using the goToSlide action.

<div>
  <amp-selector id="carouselSelector"
    on="select:carousel.goToSlide(index=event.targetOption)"
    layout="container">
    <amp-carousel id="carouselPreview"
      class="carousel-preview"
      height="72"
      layout="fixed-height"
      type="carousel">
      <amp-img option="0"
        selected
        src="https://unsplash.it/60/40?image=10"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="1"
        src="https://unsplash.it/60/40?image=11"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="2"
        src="https://unsplash.it/60/40?image=12"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="3"
        src="https://unsplash.it/60/40?image=13"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="4"
        src="https://unsplash.it/60/40?image=14"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="5"
        src="https://unsplash.it/60/40?image=15"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="6"
        src="https://unsplash.it/60/40?image=16"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="7"
        src="https://unsplash.it/60/40?image=17"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="8"
        src="https://unsplash.it/60/40?image=18"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="9"
        src="https://unsplash.it/60/40?image=19"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="10"
        src="https://unsplash.it/60/40?image=110"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="11"
        src="https://unsplash.it/60/40?image=111"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="12"
        src="https://unsplash.it/60/40?image=112"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="13"
        src="https://unsplash.it/60/40?image=113"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="14"
        src="https://unsplash.it/60/40?image=114"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="15"
        src="https://unsplash.it/60/40?image=115"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="16"
        src="https://unsplash.it/60/40?image=116"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
      <amp-img option="17"
        src="https://unsplash.it/60/40?image=117"
        width="60"
        height="40"
        alt="a sample image"></amp-img>
    </amp-carousel>
  </amp-selector>
  <amp-carousel id="carousel"
    width="400"
    height="300"
    layout="responsive"
    type="slides"
    on="slideChange:
            carouselSelector.toggle(index=event.index, value=true),
            carouselPreview.goToSlide(index=event.index)
    ">
    <amp-img src="https://unsplash.it/400/300?image=10"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=11"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=12"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=13"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=14"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=15"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=16"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=17"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=18"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=19"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=110"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=111"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=112"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=113"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=114"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=115"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=116"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=117"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
  </amp-carousel>
</div>

You can link an image gallery to a lightbox using amp-lightbox-gallery so that:

  • when user taps on image N, he enters a lightbox mode

  • user can swipe inside of lightbox mode between images

  • when user exits the lighbox mode, the carousel points to the last image seen on the lightbox

<div>
  <amp-carousel id="carousel-with-lightbox"
    width="400"
    height="300"
    layout="responsive"
    type="slides"
    lightbox>
    <amp-img src="https://unsplash.it/400/300?image=10"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=11"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=12"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/400/300?image=13"
      width="400"
      height="300"
      layout="responsive"
      alt="a sample image"></amp-img>
  </amp-carousel>
</div>

Metadata

The Top Stories carousel requires schema.org markup for one of the following types: Article, NewsArticle, BlogPosting, or VideoObject. If your Image Gallery is also a NewsArticle, you may want to mark it up as such:

    <script type="application/ld+json">
    [
      {
        "@context": "http://schema.org",
        "@type": "NewsArticle",
        ...
      },
      {
        "@context": "http://schema.org",
        "@type": "ImageGallery",
        "associatedMedia": [
          {
            "@context": "http://schema.org",
            "@type": "ImageObject",
            "contentUrl": "https://unsplash.it/60/40?image=1",
            "caption": "A cute pup"
          },
          {,
            "@context": "http://schema.org",
            "@type": "ImageObject",
            "contentUrl": "https://unsplash.it/60/40?image=2",
            "caption": "A doubly cute pup"
          },
        ],
      }
    ]
    </script>

Need further explanation?

If the explanations on this page don't cover all of your questions feel free to reach out to other AMP users to discuss your exact use case.

Go to Stack Overflow
An unexplained feature?

The AMP project strongly encourages your participation and contributions! We hope you'll become an ongoing participant in our open source community but we also welcome one-off contributions for the issues you're particularly passionate about.

Edit sample on GitHub