Scrollbound Video Ad
Summary
Sample AMPHTML ad using amp-animation, amp-video, amp-img and amp-position-observer to create an ad that animates based on scrolling.
Styling
This is an advanced example that requires some styling to make it look and function properly.
The styling designed here is responsive and will work with various ad sizes.
<style amp-custom>
/*
* Top level container: It fills the parent viewport
* that hosts the ad.
*/
.ad-container {
font-family: "Roboto", sans-serif;
position: relative;
width: 100vw;
height: 100vh;
color: #FFFFFF;
}
/* Video Layer */
.video-container {
/**
* Specifies that right corner should be used
* as the anchor point when video is scaled down
* using scrollbound amp-animation.
*/
transform-origin: calc(100% - 25px) 25px;
z-index: 2;
}
/* Video player: Click-to-player overlay */
.video-container .poster-image {
position: absolute;
z-index: 1;
}
.video-container .poster-image img {
object-fit: cover;
}
.video-container .play-icon {
position: absolute;
z-index: 3;
width: 100px;
height: 100px;
background-image: url( https://amp.dev/static/samples/img/play-icon.png);
background-repeat: no-repeat;
background-size: 100% 100%;
/* Align to the middle */
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
cursor: pointer;
opacity: 0.9;
}
.video-container amp-video video {
object-fit: cover;
}
/* Content Layer */
.content-container {
z-index: 1;
}
/* Content Layer: Background image */
.background amp-img {
margin: -70px;
}
.background amp-img img {
object-fit: cover;
}
/* Content Layer: Title and logo */
.title {
position: absolute;
top: 5px;
padding-left: 15px;
font-weight: bold;
}
/* Content Layer: Footer and learn more button */
.footer {
position: absolute;
bottom: 0;
width: 100%;
padding: 5px 15px;
background-color: rgba(0, 0, 0, 0.8);
box-sizing: border-box;
font-size: 10px;
display: flex;
flex-direction: row;
}
.footer>* {
flex: 1;
align-self: center;
}
.footer .learn-more {
background-color: #2979ff;
padding: 5px 15px;
white-space: nowrap;
flex: 0;
font-size: 10px;
letter-spacing: 0.5px;
color: #fafafa;
text-decoration: none;
}
/* Generic CSS class to fill a parent */
.fill {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
</style>
Animations
There are two types of scrollbound animations that occur in this sample: scaling of the video container and parallax movement of the background image.
The animations are implemented using amp-animation which is an AMP component that uses Web Animations API
<amp-animation layout="nodisplay" id="videoAnim">
<script type="application/json">
{
"duration": "10s",
"fill": "both",
"direction": "alternate",
"animations": [
{
"selector": "#videoContainer",
"keyframes": [
{ "transform": "scale(1)" },
{ "transform": "scale(0.5)"} ]
},
{
"selector": "#backgroundImg",
"keyframes": [
{ "transform": "translateY(0)" },
{ "transform": "translateY(60px)"}
]
}
]
}
</script>
</amp-animation>
Scale down video to the corner when scrolling: The video covers the whole ad initially and when the page scrolls, it slowly starts to scale down and move to the corner reaching its target size when the ad is in the middle of the view port.
To achieve that, we define 4 keyframes. Between 0 and 10% of viewport, video is fullsize, between 10% and 50%, it starts scaling down until it settles at half its size when in the middle of the viewport and stays the same size all the way to the last keyframe.
Parallax background image: The background image of this ad has a subtle parallax effect. To achieve that, we use scrollbound animation and specify a 60px
offset at the last keyframe.
Scrollbound Animations
The scrollbound animations are implemented using amp-position-observer which is an AMP component that Monitors the position of an element within the viewport as a user scrolls, and dispatches enter, exit and scroll events that can be used with other components
<amp-position-observer
intersection-ratios="1"
on="scroll:videoAnim.seekTo(percent=event.percent)"
layout="nodisplay">
</amp-position-observer>
Ad Container
Top level container: It fills the parent viewport that hosts the ad.
<div class="ad-container">
Video Layer
Inside the ad-container we create a click-to-play overlay and a video element.
The amp-animation
scales down the videoContainer
when the user scrolls.
<div id="videoContainer" class="video-container fill">
<div id="clickToPlayOverlay" class="fill">
<div class="play-icon" role="button" tabindex="0" on="tap:clickToPlayOverlay.hide, video.play"></div>
<amp-img class="poster-image" layout="fill" src="/static/samples/img/car-video-poster.png"></amp-img>
</div>
<amp-video id="video" controls layout="fill" src="/static/samples/video/car-video-360p.mp4"></amp-video>
</div>
Content Layer
Create the content layer that hosts the background image and information about the ad.
The amp-animation
simulates a parallax effect for backgroundImg
when the user scrolls.
<div class="content-container fill">
<div class="background">
<amp-img id="backgroundImg" layout="fill" src="/static/samples/img/car-bg.jpg"></amp-img>
</div>
<div class="title">
<div>
<amp-img layout="fixed" width="72" height="32" src="/static/samples/img/car-logo.png"></amp-img>
</div>
<div>THE ALL NEW</div>
<div>WS-X LUX</div>
</div>
<div class="footer">
<span>36 months lease, $189/month, $2999 due at signing</span>
<a href="https://ampproject.org" target="_blank" class="learn-more">LEARN MORE</a>
</div>
</div>
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-
Written by @zhouyx