Faster YouTube Embeds with JavaScript

Alexis Ulrich
Alexis Ulrich
Share

We want our visitors to get our content as fast as possible, which means the content needs to be light, and with the minimum number of requests. But we want to keep users on our pages, and be entertained. This is where embedding videos enters the scene.

Videos illustrate our textual content, bring life to it, and are often served by a third party. What more to ask? Well, there’s a hidden price tag: Videos are slow and heavy to download, even when the visitor is not watching them.

One simple video on a page called through an innocuous iframe can add up to 6 HTTP requests and as much as 450kb of content. The solution I’m proposing in this article can reduce those numbers to 1 request and about 50kb per video, along with a few bytes of JavaScript (on top of the jQuery library if you don’t like vanilla flavor).

And you know what? This solution is not new. It was previously proposed by Amit Agarwal in April 2013.

So, What’s the Trick?

In Amit’s solution, the DOM is parsed by JavaScript on document load, and each call to a YouTube video (through a special div, not a regular iframe) is replaced by a thumbnail preview to which is attached the iframe when clicking on it.

This way, we get a nice preview thumbnail still served by a third-party server that’s a fraction of the weight of the full video player. The video player is loaded only when the video is actually viewed.

My Little Added Value

I rewrote Amit’s code in plain JavaScript and with jQuery for those interested. I kept the original comments in the code to keep it as understandable as possible. My version adds a new feature in the HTML5 data parameter that enables you to add any parameter to the YouTube URL to customize your video.

YouTube offers a list of parameters to show and hide controls, branding, and info, and to set the video quality or the starting frame of your video (among other things).

  • controls: set this to 0, and the layer controls are not displayed on the video player.
  • modestbranding: set this to 1, and the YouTube logo disappears from the control bar.
  • rel: set this to 0, and no related videos will be shown when the playback of the initial video ends.
  • showinfo: set this to 0, and the player will not display information like the video title and uploader before the video starts playing.
  • start: set this to a number of seconds, and the player begins playing the video from this time (or rather from the closest keyframe).
  • vq: set this to the wanted video quality, if supported (e.g.: hd720 when high quality is available)

When adding the YouTube iframe on the click event, some parameters are given values, namely autoplay (we want the video to start as soon as its thumbnail is clicked) and autohide (to hide the video progress bar and the player controls when no interaction is detected).

Supported YouTube Thumbnails

Each YouTube video comes with a list of generated images. You can access them through the URL https://img.youtube.com/vi/<youtube-video-id>/<youtube-thumbnail> (where img.youtube.com can even be shortened to i.ytimg.com, if you prefer).

The ones we are interested in are:

  • default.jpg (default version, 120px x 90px)
  • hqdefault.jpg (high quality version, 480px × 360px)
  • mqdefault.jpg (medium quality version, 320px × 180px)
  • sddefault.jpg (standard definition version, 640px × 480px)
  • maxresdefault.jpg (maximum resolution version, 1.280px × 720px)

As an example, see this URL, which you can use to play around with the values to see the different image options.

In the following code, we use the sddefault.jpg thumbnail. Depending on your needs and the capabilities of the user’s screen, this can be replaced by any of the listed supported formats.

The HTML

The HTML code sets the YouTube video ID, styles the video size (width and height), and lists the Youtube URL parameters if needed.

<div class="youtube"
     id="fsrJWUVoXeM" 
     style="width: 500px; height: 281px;">
</div>

<div class="youtube" 
     id="lR4tJr7sMPM" 
     data-params="modestbranding=1&showinfo=0&controls=0&vq=hd720"
     style="width: 640px; height: 360px;">
</div>

The CSS

In the two videos used as examples, the picture ratio is 16:9, which returns the sddefault.jpg thumbnail with horizontal black bands. To hide them when showing this thumbnail, the background-position property is set with the center value, while setting the picture size inlined in the HTML div tag, like style="width:500px;height:281px;". This way, it is possible to show different video sizes on the same page.

The play icon, which tells the users the content is not a mere picture, is added in a layer on top of the thumbnail with an opacity transition to highlight it. We are using a data URI base64-encoded png here (from IconFinder), which saves an HTTP request and works down to IE8.

.youtube {
    background-position: center;
    background-repeat: no-repeat;
    position: relative;
    display: inline-block;
    overflow: hidden;
    transition: all 200ms ease-out;
    cursor: pointer;
}

.youtube .play {
    background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAERklEQVR4nOWbTWhcVRTHb1IJVoxGtNCNdal2JYJReC6GWuO83PM/59yUS3FRFARdFlwYP1CfiojQWt36sRCUurRIdVFXIn41lAoVdRGrG1M01YpKrWjiYmaSl8ybZJL3cd+YA//NLObd3++eO8x79z5jSq5Gw+8kov0AP8vMR5l1BtBZQM4B8ks75wCdZdYZZj5qLZ4hov2Nht9Z9vhKKSIaB/gI4M4w62KeAO6Mte4lYOq20FxrlqqOibhHmeWbvNC9ZfDX1mLae391aN6limO/gwgvAPJbWeAZuSDingdwXTBw7/0IsyaA/Fkh+KqOkD+YNfHej1QKD+y7iVlOhgLvFqFfNJvNGyuBJ+KDAF8MDd0tgS8y64OlgSdJMsysL4cG7SOHkyQZLhTee7+d2R2rAVy/S+Jd7/32ouBHAP4gNNRGQyTHc/84NhqNywZp5rvjjnnvt21aABFeCQ+RLwAf2hQ8s7sv9OCLk6AHNgQvIrvbfzKCD76g/O6cu7lf/iER/aQGgy448pExZmhdegAPhR9sObFWH1gT3lp7DaA/5bkIgJhZPgsNmz02novj+KqeApj1ubwXWe4kdyeznAgNvTpE/HQmvKqOMeuFogTUVQSRno+iaLRLAJF7uIgL9O4ubgL8aWgB7S44mNX+35YpICUiAvS9sBLkq1WzT+NFffl6AuoiApi6NT37h6sWkBIRZGkQ8YtLgyji6e1mBYTqCEBPG2Naz+0BWQgtoGoRgCzEsd9hAN1X5BfnFZASUfrSAFQNsyZ1FJASUVpHiLinDJG8U2cBZYogkrcNs5waBAGdstbeU9zdqpw0gPwwSAI6VUxHyFlDpOcHUUBBIuYNs14aZAE5RVwyzPr3/0EAEY0TyfGNjBWQvwZ +CTSbehfAH29mrID8bET0+0EUkAd8WYDOmqJ3ecsG30yr9wqRfm6Y+a1BEFDEjHfHvWmY9ck6CygHvBVr8Xhtb4ZE5HZA3y8DvBNA1TjnrmXWf+sioMwZX5V/VHXMGGMMoKdDCxCRvRWBdzKzdHEO+EisilbPyopHYqp6S9UCAsz4iojI7hUDAtyXVQgIDd6KnOoaWNkbI6FaPSuZGyMArsi7MZoloB4zviI/Nhr3X95jltwTRQmoIfgisy5ai+me67OI7fE4nrqjrqfK1t0eby0FPRB6oGVlchL3rgnfrq19RKbVBdhV9IOSwJmfmJi4vi/4ThERitwyCxVAFqydshuCX5awhQ9KtmuIWd8IDZED/nXT77rvVVv6sHRKwjYi91poqP7Dr+Y6JJ1VSZIMA3wkPNy6bX+o8Bcm0sXMdwM8Fxo0A3xORPaWBp6uPXsmbxCRD0NDL0dOANhVCXy6iAjMcjbcrMt3RITKwdMVRdFo+y5yvkL4eWZ+zHt/ZVD4dEVRNGotpst+dZZZH8k86lqn2pIvT/eqrNfn2xuyqYPZ8mv7s8pfn/8Pybm4TIjanscAAAAASUVORK5CYII=") no-repeat center center;
    background-size: 64px 64px;
    position: absolute;
    height: 100%;
    width: 100%;
    opacity: .8;
    filter: alpha(opacity=80);
    transition: all 0.2s ease-out;
}

.youtube .play:hover {
    opacity: 1;
    filter: alpha(opacity=100);
}

Vanilla JavaScript Implementation

With no dependency and the fastest implementation, the vanilla JavaScript version uses the smallest DOM ready code I could find.

Browser differences still have to be taken into account, like the lack of support for the getElementsByClassName method in IE8.

'use strict';
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
r(function(){
    if (!document.getElementsByClassName) {
        // IE8 support
        var getElementsByClassName = function(node, classname) {
            var a = [];
            var re = new RegExp('(^| )'+classname+'( |$)');
            var els = node.getElementsByTagName("*");
            for(var i=0,j=els.length; i<j; i++)
                if(re.test(els[i].className))a.push(els[i]);
            return a;
        }
        var videos = getElementsByClassName(document.body,"youtube");
    } else {
        var videos = document.getElementsByClassName("youtube");
    }

    var nb_videos = videos.length;
    for (var i=0; i<nb_videos; i++) {
        // Based on the YouTube ID, we can easily find the thumbnail image
        videos[i].style.backgroundImage = 'url(http://i.ytimg.com/vi/' + videos[i].id + '/sddefault.jpg)';

        // Overlay the Play icon to make it look like a video player
        var play = document.createElement("div");
        play.setAttribute("class","play");
        videos[i].appendChild(play);

        videos[i].onclick = function() {
            // Create an iFrame with autoplay set to true
            var iframe = document.createElement("iframe");
            var iframe_url = "https://www.youtube.com/embed/" + this.id + "?autoplay=1&autohide=1";
            if (this.getAttribute("data-params")) iframe_url+='&'+this.getAttribute("data-params");
            iframe.setAttribute("src",iframe_url);
            iframe.setAttribute("frameborder",'0');

            // The height and width of the iFrame should be the same as parent
            iframe.style.width  = this.style.width;
            iframe.style.height = this.style.height;

            // Replace the YouTube thumbnail with YouTube Player
            this.parentNode.replaceChild(iframe, this);
        }
    }
});
And here is a demo of the code in action:

See the Pen YouTube Embed Optimized with JavaScript by SitePoint (@SitePoint) on CodePen.

The jQuery Implementation

While being more expressive to my eyes and with wider browser support, the jQuery implementation comes with the price of the whole jQuery library and slightly slower performance.

"use strict";
$(function() {
    $(".youtube").each(function() {
        // Based on the YouTube ID, we can easily find the thumbnail image
        $(this).css('background-image', 'url(http://i.ytimg.com/vi/' + this.id + '/sddefault.jpg)');
    
        // Overlay the Play icon to make it look like a video player
        $(this).append($('<div/>', {'class': 'play'}));
    
        $(document).delegate('#'+this.id, 'click', function() {
            // Create an iFrame with autoplay set to true
            var iframe_url = "https://www.youtube.com/embed/" + this.id + "?autoplay=1&autohide=1";
            if ($(this).data('params')) iframe_url+='&'+$(this).data('params');
    
            // The height and width of the iFrame should be the same as parent
            var iframe = $('<iframe/>', {'frameborder': '0', 'src': iframe_url, 'width': $(this).width(), 'height': $(this).height() })
    
            // Replace the YouTube thumbnail with YouTube HTML5 Player
            $(this).replaceWith(iframe);
        });
    });
 });
And here is a demo of the jQuery version:

See the Pen YouTube Embeds Optimized (jQuery Edition) by SitePoint (@SitePoint) on CodePen.

The Final Results

Now, let’s talk about what we gain in real-world situations.

This solution was implemented on this page, which is an article that contains 3 embedded YouTube videos. Here are the results:

  • Before implementing that solution, we had 20 HTTP requests and 636.2kb of content downloaded, which took 2.22s (3.59s on load).
  • Once implemented, we went down to 17 requests, 370.7kb, and 1.05s (onload: 733ms).
  • This means 15% fewer requests, and a web page that’s 41% lighter and 52% faster (onload: 80% faster).

The results are quite good even with only one embedded YouTube video, like on this next page, which is our next example. Here are the results for the single-video page:

  • Before implementing the solution we had 20 HTTP requests and 684.4kb of content downloaded, which took 2.13s (2.14s onload).
  • Once implemented, we went down to 17 requests, 322.4kb, and 1.24s (onload: 975ms).
  • This means we ended up with 15% fewer requests, and a web page that’s 53% lighter and 42% faster (onload: 54% faster).

Conclusion

In closing, I think we can all agree that cutting down on page weight from between 40 to 50% is worth that little piece of code, don’t you think?

If you have any thoughts on the code, or would like to improve it, feel free to fork the code on CodePen or share your views in the comments.

This article is also available in French, Spanish and Portuguese.

Frequently Asked Questions on Faster YouTube Embeds with JavaScript

How can I make my YouTube embeds load faster?

YouTube embeds can be made to load faster by using JavaScript. This involves creating a ‘lite’ version of the YouTube embed. Instead of loading the entire YouTube player, you load a much smaller image and only load the full player when the user clicks on the image. This significantly reduces the initial load time and makes your page load faster.

What is the ‘modestbranding’ parameter in YouTube embeds?

The ‘modestbranding’ parameter is a feature provided by YouTube that allows you to remove the YouTube logo from the player. This is useful if you want to maintain a clean and professional look on your website or if you want to avoid any potential distractions for your viewers.

Why is my ‘modestbranding’ not working?

There could be several reasons why your ‘modestbranding’ is not working. One common reason is that you may have other parameters in your embed code that are conflicting with ‘modestbranding’. For example, if you have the ‘showinfo’ parameter set to 1, this will override the ‘modestbranding’ parameter and the YouTube logo will still be displayed.

How can I use the YouTube iFrame API?

The YouTube iFrame API allows you to control the YouTube player using JavaScript. You can use it to play, pause, or stop videos, as well as to get information about the current video and respond to events such as the player loading a video or the user clicking on the player.

What is the difference between the YouTube iFrame API and the YouTube Data API?

The YouTube iFrame API is used to control the YouTube player and respond to events in the player. On the other hand, the YouTube Data API is used to interact with YouTube itself. You can use it to search for videos, retrieve information about videos, channels, and playlists, and perform actions like commenting on videos or subscribing to channels.

How can I download YouTube videos?

Downloading YouTube videos is against YouTube’s terms of service. It is recommended to watch videos directly on YouTube or on the official YouTube app to support the content creators.

Can I customize the look of the YouTube player?

Yes, you can customize the look of the YouTube player by using the ‘theme’ and ‘color’ parameters in your embed code. The ‘theme’ parameter allows you to choose between a dark and a light theme, while the ‘color’ parameter allows you to choose the color of the player’s progress bar.

How can I make my YouTube embeds responsive?

To make your YouTube embeds responsive, you can wrap the embed code in a div and use CSS to give the div a relative width and height. Then, you can give the iframe a width and height of 100%, which will make it scale with the size of the div.

Can I autoplay YouTube videos?

Yes, you can autoplay YouTube videos by adding the ‘autoplay’ parameter to your embed code and setting it to 1. However, keep in mind that many browsers have policies that block autoplaying videos with sound, so it’s recommended to also use the ‘mute’ parameter if you want to autoplay videos.

Can I loop YouTube videos?

Yes, you can loop YouTube videos by adding the ‘loop’ parameter to your embed code and setting it to 1. However, for the loop to work, you also need to set the ‘playlist’ parameter to the same video ID as the one you’re looping.