Advanced Video Docking

Edit on Github
Open in Playground View Demo

Experimental Mode

This example uses the following experimental feature: [video-dock]. Enable the experiment via the button below. Some components require the AMP Dev Channel to be enabled as well. Learn more here.

Enable Dev Channel

Introduction

With amp-video you can have rich user interface features, such as docking (minimize-to-corner).

You can simply enable this feature on your <amp-video> by using the dock attribute. This example goes further by specifying a "docking slot" (a DOM element that represents the area where the video should be minimized) and layout synchronization using events and actions, and the amp-animation extension.

You can see the sample in action here.

Setup

Include the amp-video extension.

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

Include the amp-animation extension to animate the <aside> element on dock and undock.

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

Include styling

<style amp-custom>
  body {
    margin: 0;
    background: white;
    font-family: sans-serif;
  }

  header {
    background: white;
    padding: 10px 20px;
    border-bottom: 1px solid #ddd;
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    z-index: 1;
    line-height: 40px;
    font-size: 18px;
  }

  main {
    margin: 0 auto;
    padding: 80px 0 0 0;
    width: 100vw;
  }

  .content {
    height: 200vh;
    width: calc(70vw - 20px);
    padding: 0 20px;
    box-sizing: border-box;
  }

  aside {
    right: 20px;
    margin-left: 70vw;
    position: fixed;
    top: 80px;

    /*
    Define a viewport-based width for the aside. The docking slot will expand
    to fill its width.
    */
    width: 30vw;
  }

  .more-content {
    padding: 20px 20px 0;
    background: #eaeaea;

    /*
    Offset vertical axis by the negative height of the docking slot.
    Since the docking slot is 30vw wide, its height is 16.85vw based on a 16:9
    aspect ratio
    */
    transform: translateY(-16.85vw);
  }

  .more-content ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .more-content li {
    display: block;
    margin: 0 -20px;
  }

  .more-content li a {
    display: block;
    border-top: 1px solid #ddd;
    text-decoration: none;
    padding: 16px 20px;
    color: #2ac;
  }

  h3 {
    margin: 0;
    padding-bottom: 20px;
  }

  /* This is only needed for the preview to work on AMP by Example. You don't
  need to include these set of properties. */
  #abe-preview > div {
    width: 100vw;
    max-width: 100vw;
  }

  /* Ditto. */
  .abe-experiment-warning {
    max-width: calc(70vw - 60px);
  }
</style>

Define animations

To slide down the content below the docking slot, the vertical offset is changed into a 20px positive offset to create padding below the slot.

<amp-animation layout="nodisplay"
  id="slideDown">
  <script type="application/json">
    {
      "selector": ".more-content",
      "duration": "0.5s",
      "fill": "both",
      "easing": "ease-out",
      "keyframes": [{
          "offset": 0,
          "transform": "translateY(-16.85vw)"
        },
        {
          "offset": 1,
          "transform": "translateY(20px)"
        }
      ]
    }
  </script>
</amp-animation>

To slide up the content once the video is no longer docked, the animation reverts the aside content's offset to -16.85vw.

<amp-animation layout="nodisplay"
  id="slideUp">
  <script type="application/json">
    {
      "selector": ".more-content",
      "duration": "0.5s",
      "fill": "both",
      "easing": "ease-out",
      "keyframes": [{
          "offset": 0,
          "transform": "translateY(20px)"
        },
        {
          "offset": 1,
          "transform": "translateY(-16.85vw)"
        }
      ]
    }
  </script>
</amp-animation>

Include your video

In your <amp-video> tag, you should include two attributes:

  • dock. This attribute specifies that the video should be minimized to corner on scroll. By setting a value on the attribute, we're specifying which docking slot we're using via a CSS selector.
  • on to specify the actions that get executed on docking events. In this case, we'll start the slideDown animation on dock and the slideUp animation on undock.
<amp-video src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
  poster="https://peach.blender.org/wp-content/uploads/bbb-splash.png"
  artwork="img/bigbuckbunny.jpg"
  title="Big Buck Bunny"
  album="Blender"
  artist="Blender Foundation"
  width="720"
  height="405"
  layout="responsive"
  controls
  dock="#dock-slot"
  on="dock: slideDown.start; undock: slideUp.start">
</amp-video>

Include the docking slot.

Set width and height to 16:9. Since its layout is responsive, the slot will expand to fill the aside's width while preserving aspect ratio.

<amp-layout layout="responsive"
  width="16"
  height="9"
  id="dock-slot">
</amp-layout>

Define the content under the slot

This container is negatively offset on the vertical axis to cover the docking slot. Our slideDown animation will take care of translating this content to make room for the docking slot.

<div class="more-content">
  <h3>More Content</h3>
  <ul>
    <li>
      <a href="#">Was it an alien or something?! Click here to find out!</a>
    </li>
    <li>
      <a href="#">Baby ducks see water for the first time - Can you BELIEVE what they do?</a>
    </li>
    <li>
      <a href="#">Grocery stores HATE him: save up to 90% with this one weird trick.</a>
    </li>
    <li>
      <a href="#">When you read these 99 shocking food facts, you'll never want to eat again.</a>
    </li>
    <li>
      <a href="#">Scientists say giant asteroid could hit Earth next week, causing mass devastation.</a>
    </li>
  </ul>
</div>