Embedding YouTube videos without making your site fatter

Posted on . Updated on .

Making this site lighter and improving load times for my readers has been a priority for some years. I’ve stopped embedding web fonts, I’ve started using Unicode icons instead of relying on Font Awesome and I’ve also started loading Disqus comments on demand, which also has a positive impact on the privacy of anyone reading these pages.

However, on a few occasions I’ve wanted to embed a YouTube video in one of the posts, and I had never realized this can heavily impact page sizes and load times. Take, for example, the following HTML document.

<html>
<head><title>Embedded YouTube Video</title></head>
<body>
<iframe
    width="1280"
    height="720"
    src="https://www.youtube.com/embed/ck7utXYcZng"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
    allowfullscreen>
</iframe>
</body>
</html>

The iframe code you see above is almost verbatim copied from the code YouTube gives you when you right-click on the video and select “Copy embed code”. If you store that document locally and try to open it with Firefox using its network inspection tool, you’ll discover it attempts to load, as of the time this text is being written, around 1.84MB of data, and that’s with uBlock Origin blocking some additional requests. The largest piece of that being YouTube’s base Javascript library.

Firefox network inspection tool showing the base YouTube Javascript library weighting 1.46MB

On the one hand, it’s likely many people already have that file, and some others, in their browser cache. On the other hand, I don’t feel comfortable making that assumption and throwing my hands up. This prompted me to try to find a way to embed YouTube videos without adding so much data by default, and it turns out other people have found solutions to the problem, which I’ve slightly tuned and I’m re-sharing here. Instead of using the previous iframe code, I use something slightly more convoluted.

<html>
<head><title>Embedded YouTube Video</title></head>
<body>
<iframe
    title="Video: Why Can't You Download Videos on YouTube? How a 20-Year-Old Law Stops youtube-dl Users AND Farmers"
    height="720"
    width="1280"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
    allowfullscreen
    src="https://www.youtube.com/embed/ck7utXYcZng"
    srcdoc="
        <style>
            * {
                padding: 0;
                margin: 0;
                overflow: hidden;
            }
            html, body {
                height: 100%;
            }
            img, span {
                /* All elements take the whole iframe width and are vertically centered. */
                position: absolute;
                width: 100%;
                top: 0;
                bottom: 0;
                margin: auto;
            }
            span {
                /* This mostly applies to the play button. */
                height: 1.5em;
                text-align: center;
                font-family: sans-serif;
                font-size: 500%;
                color: white;
            }
        </style>
        <!-- The whole frame is a link to the proper embedded page with autoplay. -->
        <a href='https://www.youtube.com/embed/ck7utXYcZng?autoplay=1'>
            <img
                src='https://img.youtube.com/vi/ck7utXYcZng/hqdefault.jpg'
                alt='Video: Why Cant You Download Videos on YouTube? How a 20-Year-Old Law Stops youtube-dl Users AND Farmers'
            >
            <!-- Darken preview image laying this on top. Also makes the play icon stand out. -->
            <span style='height: 100%; background: black; opacity: 75%'></span>
            <!-- Play icon. -->
            <span>&#x25b6;</span>
        </a>"
></iframe>
</body>
</html>

The first few lines are almost identical up to the src property. I’ve only added the title property for accessibility reasons. Special care needs to be taken if the video title contains double quotes or single quotes. The src property contains the classic URL but it’s only used as a fallback for browsers that do not support the srcdoc property that starts on the next line. srcdoc allows you to specify an inline document that will be used instead of loading the frame from an external URL. Support for it is widespread nowadays. As you can see, the embedded inline document contains a style element followed by an a element pointing to the real embedded iframe, only this time with the autoplay parameter set to 1, so the video will immediately start playing when the frame is loaded.

The provided style sheet makes sure the link fills the entire embedded iframe, so clicking anywhere on it loads the video and starts playing it. Inside the link you’ll find 3 items. The first one is the video thumbnail in YouTube’s “high quality” version, which is actually lightweight and gets the job done as the background image. My guess is the name predates HD and FHD content. On top of that image I’ve placed a span element with a black background color and 75% opacity that, again, fills the whole iframe and darkens the background image, making the play button stand out. Finally, another span element is laid out on top of those, containing the Unicode character for a triangle pointing to the right in a large font. This serves as the aforementioned play button and gives readers the visual clue they need to click on the video to start playing it.

With those changes and for this particular video, the browser only needs to load around 9KB of data. You can see what it looks like below.

Edit 2020-12-08: The autoplay parameter is ignored by YouTube on mobile and users will need to tap twice to watch the video: once to click on your link and load the iframe and once more to start playing the video from it. Still, I think double tapping is worth saving almost 2MB by default. On an iPad I only need to tap once, so it depends on the exact device and what’s considered “mobile”.

Load comments