Improve Speed with Lazy-Loaded Youtube Videos (+Autoplay)
Tags: youtube, lazyload, pagespeed
Published: 2020-05-18 21:40:04

There is something addicting about webpage speed tests. I typically use <a href="https://developers.google.com/speed/pagespeed/insights/">PageSpeed Insights</a> and <a href="https://gtmetrix.com/">GTMetrix</a> to measure a website's performance upon completion. However, there is a thin line between a quick loading webpage and <i>not</i> compromising any important features. I recently found myself in a tricky position after testing out a blog site I created which primarily consisted of youtube videos. The site contains hundreds of posts, and each post contains a specific youtube video. When the user views a post, the video within the post begins auto-playing (thanks to the "?autoplay=1" parameter appended to the youtube link). Unfortunately this behavior drastically increases the load time with many requests needing to be made for resources. 

I'll be using GTMetrix to draw speed comparisons since it provides us with a more detailed break-down than PageSpeed Insights by Google.

<img src="https://dev-to-uploads.s3.amazonaws.com/i/48p2watpmfwrg7l8ltrn.png">

It took 4.8 seconds to fully load the page and 44 requests. As you can see below, a majority of these requests are being made by the embedded youtube code.

<img src="https://dev-to-uploads.s3.amazonaws.com/i/usbd6m7za7z5uhxnz3na.png">
 
After researching this issue, I found <a href="https://dev.to/haggen">Arthur Corenzan</a> on dev.to provide a very clever <a href="https://dev.to/haggen/lazy-load-embedded-youtube-videos-520g">solution</a>. By embedding the link inside the srcdoc attribute, the user will only need to download the cover image for the video. Once the image is clicked, the youtube video will load.

{% codesandbox qdzu6 %}
The first modification I made was by replacing the ▶ button with the official youtube play icon and styling it to appear in the middle of the cover image. Although the iframe code resolved my speed issue, it required the user to click the cover image for the video to begin playing. I fixed this by adding a script to the footer of my post which automatically clicks the cover-image once the page is loaded. If you're not interested in auto-playing the video, please ignore the function below.

``` javascript
window.onload = function () {
setTimeout(function () {
document.querySelector('#videoframe').contentDocument.querySelector('#playbutton').click();
  }, 2000);
};
```
You can change the value to a number below 2000 but be cautious. If the video is auto-clicked before the page has finished loading, then we are back to square one (if anyone has a better solution please share).

Below is my final iframe code:

``` html
<iframe
  width="100%"
  height="100%"
  id="videoframe"
  srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{background:#000;height:100%}img{position:absolute;width:100%;top:0;bottom:0;margin:auto}</style>
  <a href=https://www.youtube-nocookie.com/embed/YOUTUBE_VIDEO_ID?autoplay=1&modestbranding=1&iv_load_policy=3&theme=light&playsinline=1>
  <img src=https://img.youtube.com/vi/YOUTUBE_VIDEO_ID/hqdefault.jpg>
  <img id='playbutton' src='YOUTUBE_PLAY_BUTTON_IMAGE_URL' style='width: 66px; position: absolute; left: 41.5%;'></a>"
  frameborder="0"
  allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
  allowfullscreen
  scrolling="no" 
  loading="lazy"
 style="background-color: #000" 
></iframe>
```
I've shared the youtube play icon <a href="https://imgur.com/TlY8mbW">here</a>, feel free to download it and host it on your own server. I'm also using the hqdefault version of the youtube video thumbnail. You can try maxresdefault if you want a higher quality image but not every video has a maxresdefault image. You can use this <a href="https://boingboing.net/features/getthumbs">tool</a> to see which image versions of the video are available.

Now let's test the page speed with the new iframe code:

<img src="https://dev-to-uploads.s3.amazonaws.com/i/oi892fclt0hpniv75yc2.png">

We've drastically cut down the load time and the requests! The user won't notice anything different and the video is still auto-playing as it was before we implemented the new iframe code. If the user manages to click the play button before the script does, the video will still play without any issues.

Final result:

<img src="https://dev-to-uploads.s3.amazonaws.com/i/aeuazbbtm2dcgi74r0bf.gif">