DEV Community

Arthur Corenzan
Arthur Corenzan

Posted on • Updated on

Lazy load embedded YouTube videos

I was working on this simple static website that should have an YouTube video displayed right on the landing page. So I went my merry way, hopped onto YouTube, snatched the embed code, pasted it into my editor and called it a day.

YouTube share dialog

The thing is the job was specifically to deliver high performance, accessibility and modern practices, so you can imagine my annoyance when I noticed that just for having this <iframe> I got this:

DevTools snapshot showing multiple requests made from YouTube's iframe 🤨️

Plus a few extra requests that my ad blocker handled for me.

That is over 500KB that my users would have to download on top of the website, regardless if they'll watch the video. Do you have any idea how heavy this might hit your users, specially the ones with slow connection or low performing machines? To add insult to injury they'd also be being tracked—Hi Google—for just loading a video they didn't even know was there.

It being a simple static website I wanted to keep my solution to a minimum, so here's what I came up with.

The code for embedding an YouTube video, as of August 2019, goes like this:

<iframe 
  width="560" 
  height="315" 
  src="https://www.youtube.com/embed/Y8Wp3dafaMQ" 
  frameborder="0" 
  allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" 
  allowfullscreen>
</iframe>
Enter fullscreen mode Exit fullscreen mode

So I thought what if instead of the actual video I showed just its cover linked to the video? It would still kinda look like an embedded video but it would require only a single image upfront. Thankfully YouTube has an URL schema for video thumbnails.

<a href="https://www.youtube.com/embed/Y8Wp3dafaMQ">
  <img src="https://i3.ytimg.com/vi/Y8Wp3dafaMQ/hqdefault.jpg">
</a>
Enter fullscreen mode Exit fullscreen mode

Cool, but I really don't want to have to create a whole new page just for this teeny tiny snippet of code. Well, we're in luck cause <iframe> has just the perfect thing for us—the srcdoc attribute. With it you can source the <iframe> directly in the hosting page. Just beware that it won't work on Edge or IE and that we can't use double quotes.

<iframe 
  ...
  srcdoc="<a href=https://www.youtube.com/embed/Y8Wp3dafaMQ><img src=https://i3.ytimg.com/vi/Y8Wp3dafaMQ/hqdefault.jpg></a>">
</iframe>
Enter fullscreen mode Exit fullscreen mode

Finally you'll notice that if we click the image it'll load the video but in a paused state and we would need to click it again to start watching. Fret not, cause the embed video URL supports player parameters and among those there's the autoplay variable which does exactly what you would expect. Additionally due to browser's default style users on systems with scrollbar—namely not macOS—will see an unnecessary scrollbar, but nothing that a small CSS reset wouldn't fix.

Remy Sharp pointed out we should keep the src as fallback to browsers that don't support srcdoc. Adrian Roselli suggested a few tweaks to improve accessibility. Also, while applying these suggestions I fixed the image position so it stays centered both horizontally and vertically without resorting to background-size: cover. Thank you guys for your feedback! 🤩️

Here's the final result:

The <iframe> singled out:

<iframe
  width="560"
  height="315"
  src="https://www.youtube.com/embed/Y8Wp3dafaMQ"
  srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href=https://www.youtube.com/embed/Y8Wp3dafaMQ?autoplay=1><img src=https://img.youtube.com/vi/Y8Wp3dafaMQ/hqdefault.jpg alt='Video The Dark Knight Rises: What Went Wrong? – Wisecrack Edition'><span>▶</span></a>"
  frameborder="0"
  allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
  allowfullscreen
  title="The Dark Knight Rises: What Went Wrong? – Wisecrack Edition"
></iframe>
Enter fullscreen mode Exit fullscreen mode

This way all the users will have to download upfront is the cover image, which seems pretty reasonable to me. You can customize it further, e.g. make use of the different thumbnail sizes for different devices, and if you need more control over what the user will load and what features to enable you can always explore the YouTube Player API.

If you've got any questions, corrections or suggestions feel free to comment below. Thank you for your time. 😊️

Top comments (34)

Collapse
 
remy profile image
Remy Sharp

Great post. I wrote a reply on my blog about better support: remysharp.com/2019/08/09/redux-laz... - but the TL;DR is: add the src attribute as a fallback for when srcdoc isn't supported 👍

Collapse
 
haggen profile image
Arthur Corenzan

Well pointed out. I have edited the post. Thank you!

Collapse
 
aardrian profile image
Adrian Roselli • Edited

Three suggestions:

  • add a title attribute to the <iframe> (excluding it is a WCAG failure, one which Google continues to ignore),
  • consider a method to put a "Play" image over the video thumbnail so users understand it will play a video, and not just send them to a new page or load an image,
  • put an alt attribute on the image.

I mocked one up on CodePen: codepen.io/aardrian/pen/pMVWxQ

Debug view: s.codepen.io/aardrian/debug/pMVWxQ

Collapse
 
haggen profile image
Arthur Corenzan

Great suggestions! I have edited the article to reflect this change. Thank you!

Collapse
 
doveranalyst profile image
RJ Mrunmayee

Hi! I wrote you a reply here:
doveranalyst.com/2020/12/how-to-lo...

It is working on desktop but on mobile devices the autoplay is not working.
And the Unicode use does not stay Unicode like. Have shared screenshots.
Please have a look.

Collapse
 
ceap80 profile image
Cesar Arguinzones

The video is not autoplaying on my mobile device, a Moto G4 Play. For some reason I have to double click 😞

Collapse
 
simevidas profile image
Šime Vidas

Can I haz <lazy-youtube> web component? 😁

Collapse
 
tomayac profile image
Thomas Steiner

My exact same thoughts. This wants to be abstracted away.

Collapse
 
arberbr profile image
Arber Braja

Very nice and simple solution.

Speaking from personal experience having worked on the past with video heavy website.

Collapse
 
haggen profile image
Arthur Corenzan • Edited

Now it might as well be a video light website. 😂️

Collapse
 
doveranalyst profile image
RJ Mrunmayee • Edited

My God you're a lifesaver! Just implemented this on doveranalyst/p/videos.html
A quick solution for the playlist embed not working was to replace ?rel=0 with &rel=0.
Added modest branding also.
Looks delicious on desktop version.
But on mobile version a bright blue play icon comes.
Is there any way to have same white dupe you created in style to show on mobile chrome?
And is there any way we can have this style for the play and image placement done only once?
God bless ya.
I was tired of JavaScript making page load so bad.
My page speed score changed from 30 to 70 google page insights after this change🤩🤩🤩

Collapse
 
marcusjt profile image
Marcus

Clearly you originally used the video youtube.com/watch?v=27rhHfBugnc then changed your mind but didn't update the IMG SRC URLs, which makes it a little confusing (especially the bit about the YouTube URL schema for video thumbnails) so please update code snippets 2/3/4 accordingly! ;)

Collapse
 
haggen profile image
Arthur Corenzan • Edited

You're most correct, sir. The thing is I checked those so many times and it still slipped. 😅️ Well, it should be fixed now. Thank you!

Collapse
 
jelle619 profile image
Jelle Z.

Using autoplay is not ideal, as more and more browsers, especially mobile ones, don't support it. This means that on these browsers, you will have to double tap/click, which feels a little bit clunky in my opinion.

Collapse
 
haggen profile image
Arthur Corenzan

That's true, it doesn't work on mobile and it's not ideal but I still think it's better than having your users download half a megabyte of junk. I've been thinking about it although I haven't found a good alternative just yet. In any case I should point this out in the post. Thank you for your comment!

Collapse
 
jelle619 profile image
Jelle Z. • Edited

YouTube has an JavaScript-based embed API. In HTML, you can defer external JavaScript until the page has finished parsing. This way, the video player will only load after other parts of the page have been loaded first. While this won't decrease the amount of data that will get downloaded or prevent tracking by Google, it will allow people with a poor internet connection to comfortably view the page whilst the video player is taking its time to load in the background.

Here's a CodePen: codepen.io/jelle619/pen/yLBVyWY

If you don't like using this method, you could still make videos automatically play on browsers which, on the surface, don't seem to support autoplay. Some browsers have started blocking autoplay because it allows web pages to play sound without the user's permission which can be unwanted. However, in many instances, browsers that do this will still allow autoplay when the video has been muted.

Collapse
 
lucid00 profile image
Hugh Isaacs II

Might as well add the loading="lazy" attribute to the iframe (or even the IMG tag) for bonus lazy loading.

web.dev/native-lazy-loading

Collapse
 
jelle619 profile image
Jelle Z.

Great find! I didn't know this feature also supports iframe... 😅 I hope it will be introduced to other browsers besides Chrome soon.

Collapse
 
jarednewnum profile image
Jared Newnam • Edited

How can I handle the autoplay function since Chrome 66?

I want the user to be able to click play just once. Unfortunately, this method requires autoplay be true. In order for autoplay to work properly, mute also has to be set (mute=1).

But then the user will have to unmute once the video starts playing. How can I avoid that additional step?

Collapse
 
hasyemiraws profile image
hasyemi rafsanjani asyari widiandi sunardi

Hi thanks for the post, great tips!
I have a question with this approach. So I'm having a problem with the video (it's my own video on youtube) that I embed on the website but it doesn't get tracked/showing up as external source pointing to the website in my Youtube Studio, do you happen to know what might be the issue?

Collapse
 
moviezdotbiz profile image
Moviez.biz

Hai It really increased the loading speed of my blog posts , but its not fetching the thumbnail for related posts in my blogger blog , you can check the url here insidethemovie.com/2020/05/the-sec... so can you please tell me how to modify so that my theme code can fetch the thumb nail img. Also tell me how to make it responsive in desktop. Thank You

Collapse
 
doveranalyst profile image
RJ Mrunmayee

For related posts, you have to add ?rel=0 (if you want to show only your videos in suggestions.
And for playlists you will have to add &rel=0
See here
doveranalyst.com/2020/12/how-to-lo...

Collapse
 
gaffen profile image
Gaffen

I really like this; glad to see it working without javascript. Think I need to give it a shot!

Collapse
 
alex1blackhole profile image
Nason Truhach

codepen.io/alex1blackhole/pen/KKPW...

I use this method for lazy-load video

Collapse
 
krisc profile image
k-risc

For anyone who would also like to compare the approach explained on this page with other approaches: I used github.com/mike-zarandona/PrettyEm... back in the time.

Collapse
 
arvindpdmn profile image
Arvind Padmanabhan

Expecting users to click twice is a problem. Firefox does autoplay but not Chrome.

Collapse
 
vivelapub profile image
VivelaPub

Hi Arvind. I had the exact same issue bugging me for a long time. All lazyloading codes and plugins I tried required 2 clicks on mobile for YouTube videos to play, and not only in Firefox! I've finally managed to make it work with 1 click even on mobile using the YouTube API V3. I've made a WordPress plugin out of it if someone is interested. You can see a demo here thinksmall.me/ and view its code.

Collapse
 
doveranalyst profile image
RJ Mrunmayee

Works on Chrome Mozilla, Edge for me with just one click.
Have a look doveranalyst.com/p/videos.html

Collapse
 
thesureshg profile image
Suresh Kumar Gondi

This works cool, and a lot weight has been reduced. Just that we need to make the final iframe code responsive.

I did checked it's not responsive yet.

Thanks for the awesome job, mate.

Collapse
 
doveranalyst profile image
RJ Mrunmayee

Inorder to make it responsive you just have to add a div class with responsive iframe (whatever you've set in your css).

Put this whole code inside a parent

and it is responsive.

Demo:

doveranalyst.com/p/videos.html
Collapse
 
thesureshg profile image
Suresh Kumar Gondi

Thank you :)