YouTube Performance Switcheroo

I was really happy with my YouTube intro vid for GeoPortal. I wasn’t happy with what it did to my page load time. It added >1s to the load time, ~300KB to the page weight, and did some unpleasant style flashing as the player loaded. For a video that some users would watch once, that sucks. Time to give it the forearm shiver.

Faster YouTube embeds is not a new idea. It involves putting an image where the YouTube video is going to go, along with a play button, and then building the iframe on the fly if somebody clicks on it. I found a number of plugins for this using jQuery, but GeoPortal doesn’t use jQuery. I took my favorite by Jesse Schoberg and recreated it in plain JavaScript.

The container has an optional data-background argument so you can specify an image to stick in there. By default it pulls the default image for the video from YouTube. The id tag is the YouTube id, and the data-params are appended to the URL. The JavaScript picks up anything with identifier you pass to it, in this case youtube.

1
<div class="youtube" id="DtEIu-h2FQo" data-params="controls=0&showinfo=0&rel=0" data-background="img/youtube-bg.png"></div>;

The CSS is almost entirely from Jesse Schoberg’s code. It’s dropping a responsive play button in the middle of the container.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
.youtube { /* container (responsive) */
position: relative;
cursor: pointer;
background: no-repeat center center / cover;
padding-bottom: 56.25%; /* 16:9 */
height: 0px;
clear:both;
margin: 20px 0 30px;
}

.youtube::before { /* play bubble */
content: '';
background: rgba(255, 255, 255, .6);
height: 80px;
width: 80px;
display:block;
margin: -40px 0 0 -40px;
border-radius: 100px;
position: absolute;
top: 50%;
left: 50%;
box-shadow: 0 0 20px 3px rgba(51, 51, 51, .8);
transition: all .1s ease;
z-index:1;
}

.youtube:hover::before { /* play bubble hover */
background: rgba(238, 238, 238, .8);
box-shadow: 0 0 10px 3px rgba(51, 51, 51, .8);
width: 100px;
height: 100px;
margin: -50px 0 0 -50px;
}

.youtube::after { /* Play Triangle */
content: '';
width: 0;
height: 0;
line-height:0px;
display:block;
border-style: solid;
border-width: 20px 0 20px 40px;
margin: -20px 0 0 -15px;
border-color: transparent transparent transparent #333;
position: absolute;
top: 50%;
left: 50%;
height: 0;
width: 0;
z-index:2;
}
.youtube iframe{ /* youtube embed (responsive) */
width:100%;
height:100%;
position:absolute;
top:0;
left:0;
z-index:3;
}

And now to the JavaScript, which I’ve rewritten into plain JavaScript as a CommonJS module.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function youtubeLoader(identifier) {
var collection = document.querySelectorAll(identifier);

// loop through collection
for (var i = 0; i < collection.length; ++i) {
var theElem = collection[i];
var id = theElem.getAttribute("id");

// set background image
if (theElem.hasAttribute('data-background')) {
theElem.style.backgroundImage = 'url(' + theElem.getAttribute('data-background') + ')';
} else {
theElem.style.backgroundImage = 'url(//i.ytimg.com/vi/' + id + '/hqdefault.jpg)';
}

// on click create the iframe and drop it in
theElem.addEventListener("click", function(e) {
// build iframe
var iframe = document.createElement('iframe');
var url = '//www.youtube.com/embed/' + id + '?autoplay=1&autohide=1&' + theElem.getAttribute('data-params');
iframe.src = url;
iframe.setAttribute('allowfullscreen', 'allowfullscreen');
iframe.setAttribute('frameborder', '0');
theElem.appendChild(iframe);
});
};

}

if (typeof module === 'object') {
module.exports = youtubeLoader;
}

To call it, do a youtubeLoader('.youtube');.

The results are pretty dramatic. With the YouTube vid directly in the page, page load time was 1.4s, page finish time was 2.14s, and page weight was 934kb. By using the above to load the YouTube iframe on demand, page load time went down to 0.633s, page finish time went down to 0.735s, and page weight went down to 652kb. That’s a serious, noticeable performance boost. As an added bonus, no more ugly style flashing from the YouTube iframe on page load.

Must go Faster