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:

A panel with Antonio Damasio, David Chalmers, and Marcelo Gleiser
The Mystery of Consciousness. A conversation between neuroscientist Antonio Damasio and philosopher David Chalmers.

The implementation logic goes as follows:

  1. Use a div that will receive the video content, and wrap it inside a figure. We’ll need this div for both the UI and the responsive embed.
  2. Put a “play video” button inside the div for accessibility.
  3. Put a static thumbnail img after the button.
  4. Add a click event listener to the whole div.
  5. On click, replace the div content with the embed code.
  6. 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.
  7. Add the full link to the video inside a noscript tag in the figcaption.

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" webkitAllowFullScreen 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:


https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg
YouTube thumbnail URL. Replace “VIDEO_ID” with the actual video ID.