Just-in-time video embed
How to embed external videos without loading all the bundled code upfront.
I have some web pages with many embedded external videos. When I include the YouTube or the Vimeo embed code directly, the web page makes a lot of requests and loads up significant code bundles whether the user plays the videos or not. I needed a way to embed the video but only load the bundled code when needed.
The solution I found is to show a thumbnail and replace it with the full embed code only when the user clicks the image. Here’s an example:
The implementation logic goes as follows:
- Use a
div
that will receive the video content, and wrap it inside afigure
. We’ll need this div for both the UI and the responsive embed. - Put a “play video”
button
inside the div for accessibility. - Put a static thumbnail
img
after the button. - Add a click event listener to the whole div.
- On click, replace the div content with the embed code.
- Show a loading message by appending a pseudo-element to the div. This pseudo-element is styled like the button, and will be visible while the iframe is loaded into the div. The higher
z-index
of the iframe will cover the loading message. - Add the full link to the video inside a
noscript
tag in thefigcaption
.
Below is the actual code.
YouTube
<figure>
<div class="embed_responsive">
<button class="play_button">Play Video</button>
<img class="thumbnail" src="thumbnail.jpg" alt="description text">
</div>
</figure>
<script type="text/javascript">
(function(){
var video_container = document.querySelector('figure .embed_responsive');
var video_id = '8FEqHisBVUM';
var options = '?vq=hd1080&rel=0&iv_load_policy=3&autoplay=1';
video_container.addEventListener('click', function(){
video_container.classList.add('loading');
video_container.innerHTML = '<iframe src="https://www.youtube.com/embed/' + video_id + options + '" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>';
}, false);
})();
</script>
Notice how YouTube embed options are stored separately in a variable. These options set the default playback to Full HD when available, remove the suggested videos when the user pauses playback, and autoplay the video. Autoplay works on desktop only. On mobile, the user has to click twice to play the video. That’s the downside of this method.
Vimeo
<figure>
<div class="embed_responsive">
<button class="play_button">Play Video</button>
<img class="thumbnail" src="thumbnail.jpg" alt="description text">
</div>
</figure>
<script type="text/javascript">
(function(){
var video_container = document.querySelector('figure .embed');
video_container.addEventListener('click', function(){
video_container.classList.add('loading');
video_container.innerHTML = '<iframe src="https://player.vimeo.com/video/36579366?autoplay=1 frameborder="0" webkitAllowFullScree mozallowfullscreen allowFullScreen></iframe>';
}, false);
})();
</script>
CSS
.embed_responsive{
position: relative;
max-width: 100%;
height: 0;
padding-bottom: 56.25%;
overflow: hidden;
background: #000;
}
.embed_responsive iframe{
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 11;
}
.embed_responsive .thumbnail{
display: block;
max-width: 100%;
height: auto;
margin: auto;
cursor: pointer;
}
.embed_responsive .play_button{
display: block;
padding: 0;
border: none;
-webkit-appearance: none;
overflow: visible;
}
.embed_responsive .play_button,
.embed_responsive.loading:before{
content: 'Loading...';
position: absolute;
width: 9em;
height: 2em;
left: 50%;
top: 50%;
margin-left: -4.5em;
margin-top: -1em;
color: #fff;
text-align: center;
font-family: "Futura-PT", sans-serif;
font-weight: 600;
font-size: 1.5em;
line-height: 2em;
background: #e10000;
border-radius: 0.25em;
transform: scaleX(0.95) scaleY(1.05);
cursor: pointer;
z-index: 10;
}
.embed_responsive:hover .play_button{
background: #f50000;
}
.embed_responsive .play_button:focus{
outline: none;
box-shadow: 0 0 0 4px #fff;
}
Thumbnails
The thumbnails I use are either retrieved from the video provider, or custom ones if those provided aren’t good enough. The following canonical URL serves the highest definition thumbnail available for a YouTube video:
Links
- Get Thumbnail of a Video: works for both YouTube and Vimeo.
- Jag Talon, Embed Bud, 2018. A tool to create a more private wrapper around YouTube’s player. This cool tool prompted me to write this blog post.
- Outstanding talks: a page full of just-in-time embedded videos.