Youtube embed preview image

Let’s take the following situation: you have lots of YouTube embeds on a page and the page is loading extremely slow ( sometimes not loading at all! ) – what can be done?

Fortunately I had to fix this exact problem for a client recently and here’s the approach I used. Instead of adding the actual YouTube iframe by default I thought a good approach would be to use the video’s thumbnail which on click would be replaced by the iframe.

Getting the YouTube video’s thumbnail image

First you need the YouTube video id, let’s take for example: https://www.youtube.com/watch?v=VdphvuyaV_I – in this case the id is: “VdphvuyaV_I”.

Next you have to decide on the image size, there are 4 size available ( more info here ): default, medium quality, standard quality and high quality. I usually use the high quality size which is 480px x 360px.

So in our case the thumbnail url is: https://img.youtube.com/vi/VdphvuyaV_I/hqdefault.jpg – notice the video id in the url.

Making the thumbnail clickable

Next up is adding a JavaScript action that will switch the image to the iframe on click. I chose to include the full embed url – in case you want to use this with Vimeo ( it’s possible ). So the markup is:

<div class="m_load_here">
<img src="https://img.youtube.com/vi/VdphvuyaV_I/hqdefault.jpg" alt="YouTube Video" />
<a class="m_overlay" href="#" data-src="//www.youtube.com/embed/VdphvuyaV_I?wmode=transparent&autoplay=1">
</div>

I recommend placing this inside a div with the styling of your choice, for example 3 columns per row. And the js needed to do the switch:

<script type="text/javascript">
   jQuery( function ($) {
      $('.m_overlay').click(function (e) {
         e.preventDefault();
         var th = $(this);
         var embed_url = th.data('src');
         var width = th.width();
         var height = th.height();
         var iframe = '<iframe src="'+embed_url+'" width="'+width+'" height="'+height+'"></iframe>';
         th.parent().html(iframe);
      });
   });
</script>

Styling it to look like a video

Because we are replacing a video we should make it look similar, so what we’ll also need is the video title. The easiest way to get that without using the annoying YouTube API that needs authentication is using the oEmbed feature.

In a WordPress context I would store the video info in a transient. Use this code to only pull the video title once a month:

$id = 'VdphvuyaV_I';
$video_title_transient = get_transient('m_yt_title_'.$id);
if ( !$video_title_transient ) {
   $video_info = file_get_contents('https://www.youtube.com/oembed?url=http://www.youtube.com/watch?v='.$id.'&format=json');
   $video_info = json_decode($video_info);
   if ( $video_info && isset($video_info->title) ) {
      $video_title_transient = $video_info->title;
      set_transient('m_yt_title_'.$id, $video_title_transient, MONTH_IN_SECONDS);
   }
}

Next step is to place these over the thumbnail so they look similar to the embed. The html I used is:

<div class="m_load_here">
<img src="https://img.youtube.com/vi/VdphvuyaV_I/hqdefault.jpg" alt="YouTube Video" />
<a class="m_overlay" href="#" data-src="//www.youtube.com/embed/VdphvuyaV_I?wmode=transparent&autoplay=1">
<span class="m_yt_title"><?php echo $video_title_transient; ?></span>
<span class="m_yt_button"><svg height="100%" version="1.1" viewBox="0 0 68 48" width="100%"><path class="ytp-large-play-button-bg" d="m .66,37.62 c 0,0 .66,4.70 2.70,6.77 2.58,2.71 5.98,2.63 7.49,2.91 5.43,.52 23.10,.68 23.12,.68 .00,-1.3e-5 14.29,-0.02 23.81,-0.71 1.32,-0.15 4.22,-0.17 6.81,-2.89 2.03,-2.07 2.70,-6.77 2.70,-6.77 0,0 .67,-5.52 .67,-11.04 l 0,-5.17 c 0,-5.52 -0.67,-11.04 -0.67,-11.04 0,0 -0.66,-4.70 -2.70,-6.77 C 62.03,.86 59.13,.84 57.80,.69 48.28,0 34.00,0 34.00,0 33.97,0 19.69,0 10.18,.69 8.85,.84 5.95,.86 3.36,3.58 1.32,5.65 .66,10.35 .66,10.35 c 0,0 -0.55,4.50 -0.66,9.45 l 0,8.36 c .10,4.94 .66,9.45 .66,9.45 z" fill="#1f1f1e" fill-opacity="0.81"/><path d="m 26.96,13.67 18.37,9.62 -18.37,9.55 -0.00,-19.17 z" fill="#fff"/><path d="M 45.02,23.46 45.32,23.28 26.96,13.67 43.32,24.34 45.02,23.46 z" fill="#ccc"/></svg></span>
</div>

You will notice this is the actual SVG for the YouTube button, and below is the CSS:

   .ytp-large-play-button-bg {
      fill: #1f1f1f;
      fill-opacity: 0.81;
      transition: fill 0.1s cubic-bezier(0.4, 0, 1, 1) 0s, fill-opacity 0.1s cubic-bezier(0.4, 0, 1, 1) 0s;
   }
   .m_overlay:hover .ytp-large-play-button-bg {
      fill: #cc181e;
      fill-opacity: 1;
      transition: fill 0.1s cubic-bezier(0, 0, 0.2, 1) 0s, fill-opacity 0.1s cubic-bezier(0, 0, 0.2, 1) 0s;
   }
   .m_yt_button {
      background: rgba(0, 0, 0, 0) none repeat scroll 0 0;
      border-radius: 10px;
      height: 30px;
      left: 50%;
      position: absolute;
      top: 50%;
      transform: translate(-50%, -50%);
      width: 42px;
      z-index: 5;
      display: block;
   }
   .m_overlay {
      left: 0;
      top:0;
      right: 0;
      bottom :0;
      position: absolute;
   }
   .m_yt_title {
      color: #FFF;
      outline: 0 none;
      text-decoration: none;
      transition: color 0.1s cubic-bezier(0, 0, 0.2, 1) 0s;
      float: left;
      max-width: 100%;
      overflow: hidden;
      overflow-wrap: normal;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: 18px;
      padding: 14px 16px 0;
   }