Perfect YouTube Core Web Vitals

Learn how to embed YouTube videos without losing PageSpeed

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-02-26

Perfect YouTube Core Web Vitals

YouTube videos are a great way to enhance your page. The user experience of added videos is just amazing. 

No matter how hard you try, YouTube videos will always slow down the page if you embed them using the default YouTube embed code.

In this short article I will show you how to speed up your page and embed YouTube videos without losing PageSpeed.

Last reviewed by Arjen Karel on February 2026

youtube placeholder for pagespeed

How to embed a YouTube video (the slow way)

YouTube has made it pretty simple to embed a video on your page. First navigate to the video page and click on share below the video

youtube share button

Next select embed and copy the embed code:

slow youtube embed code

Copy the code and paste it into the HTML of your site. When you then run a Lighthouse audit you will notice that all the important metrics like First Contentful Paint, Speed Index, Largest Contentful Paint and the Total Blocking Time have increased by about 1 to 1.5 seconds. A standard YouTube embed loads between 1.3 and 2.6 MB of JavaScript, CSS, fonts, and tracking scripts. It makes over 20 HTTP requests to 8 to 10 different domains. All of that happens before the visitor even presses play. Let's fix this:

Default YouTube embed

youtube embed slow lighthouse results

Smart YouTube embed

fast youtube embed lighthouse results

Fix the YouTube Core Web Vitals!

We are going to fix the Core Web Vitals by creating a placeholder for the image. During page load the placeholder will be loaded. Only when we actually need the YouTube video will we change the placeholder for the actual video. This is called the facade pattern: show a lightweight stand-in first, load the heavy third-party resource only on interaction. The same technique works for Google Maps and chat widgets.

Step 1: Download the placeholder image

Downloading the placeholder image is real easy. Look at the url for the YouTube video. For this example we will use this url: https://www.youtube.com/watch?v=Oxv6IRcuNaI

As you might notice there is a variable in the url: 'Oxv6IRcuNaI'. Copy that variable and paste it into the default image location for any YouTube video https://i.ytimg.com/vi_webp/Oxv6IRcuNaI/maxresdefault.webp

Open that url, right click the image and select 'save image as'. After you have downloaded the image resize it to your needs.

Step 2: Create the placeholder

The next step is to create the placeholder. I am going to use a relative positioned div, place an image with object-fit:cover and an empty iframe that we will populate later. For privacy, you can use youtube-nocookie.com instead of youtube.com in the embed URL. This prevents YouTube from setting tracking cookies until the video actually plays.

<div id="ytplaceholder">
   <img class="ytcover"
        loading="lazy"
        width="560"
        height="315"
        src="https://i.ytimg.com/vi_webp/Oxv6IRcuNaI/maxresdefault.webp">
   <iframe
       id="ytiframe"
       width="560"
       height="315"
       data-src="https://www.youtube-nocookie.com/embed/Oxv6IRcuNaI">
   </iframe>
</div>

So far so good, now let's add some styling. The padding in the YouTube placeholder is a little trick to ensure the video scales on all devices. The image is placed absolute at the top and has an object-fit:cover property. This mimics a background image but allows for lazy loading and responsive images. Finally the iframe itself has an absolute position and covers the entire placeholder once it is visible.

#ytplaceholder {
    position: relative;
    position: relative;
    overflow: hidden;
    padding-top: 56.25%;
}

#ytplaceholder img {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    object-fit: cover
}

#ytplaceholder iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: 0;
    opacity: 0;
    transition: opacity 2.4s ease 0s;
}

Now for the magic: let's change the placeholder image to an actual video. I add an event listener to the YouTube placeholder. Once a visitor hovers over the image the YouTube iframe loads and becomes visible because of the opacity change.

<script>
// youtube placeholder
var ytplaceholder = document.getElementById ('ytplaceholder');

// change the video
var videolistner = function(e) {
   var ytiframe = document.getElementById('ytiframe');
   ytiframe.src = ytiframe.getAttribute('data-src');
   ytiframe.onload = ytiframe.style.opacity = 1;
   ytplaceholder.removeEventListener("mouseover", videolistner);
};

//listen to the mouseover event to change the video
ytplaceholder.addEventListener('mouseover', videolistner);

Always show the YouTube video

Let's go one step further and queue the YouTube video to always replace the placeholder image even without any interaction. I do not want to do that right away, let's wait until the browser is idle. I'll use a setTimeout for simplicity but the requestIdleCallback() method would be a great choice as well. Note that requestIdleCallback is not yet supported in Safari by default. Use a fallback: const idle = window.requestIdleCallback || ((cb) => setTimeout(cb, 1));

<script>
var ytplaceholder = document.getElementById ('ytplaceholder');

var videolistner = function (e) {
   var ytiframe = document.getElementById ('ytiframe');
   ytiframe.src = ytiframe.getAttribute ('data-src');
   ytiframe.onload = ytiframe.style.opacity=1;
   ytplaceholder.removeEventListener ("mouseover", videolistner);
   };

ytplaceholder.addEventListener ('mouseover', videolistner);

// show the YouTube video anyway after 3 seconds
setTimeout(function(){
   videolistner();
},3000);
</script>

Here you go guys, a perfect page-speed score with an embedded YouTube video in just a few lines of code.

Alternative: the srcdoc technique

If you want to avoid JavaScript entirely, you can use the srcdoc attribute on the iframe. This embeds a mini HTML page (just the thumbnail and a play button) directly in the iframe tag. When the visitor clicks play, the browser replaces it with the actual YouTube player.

<iframe
   src="https://www.youtube-nocookie.com/embed/VIDEO_ID?autoplay=1"
   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-nocookie.com/embed/VIDEO_ID?autoplay=1>
   <img src=https://i.ytimg.com/vi_webp/VIDEO_ID/maxresdefault.webp
   alt='Video title'><span>&#x25BA;</span></a>"
   width="560"
   height="315"
   loading="lazy"
   allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
   allowfullscreen>
</iframe>

The srcdoc approach loads zero external resources until the visitor interacts. The tradeoff is that on some mobile browsers it requires two taps (one to activate the srcdoc link, one to play the video).

Production ready: lite-youtube-embed

If you prefer a drop-in solution, Paul Irish's lite-youtube-embed web component does all of this in a single custom element. It is roughly 224 times faster than the default YouTube embed and is the solution recommended by web.dev.

<lite-youtube videoid="Oxv6IRcuNaI"></lite-youtube>

It handles the thumbnail, the play button, responsive sizing, and accessibility out of the box. It uses youtube-nocookie.com by default.

Extend this technique

Of course this is just a simple example that only works for a single YouTube video with a specific id. On your site it would be a good idea to attach the event listener to a querySelector and also attach an IntersectionObserver to automatically load YouTube videos before they scroll into view. However you want to extend it: the idea stays the same!

Across sites monitored by CoreDash, pages using a YouTube facade pattern have an average LCP that is [CD:placeholder]ms faster than pages loading the embed directly. If you have implemented the facade pattern, use Real User Monitoring to verify the improvement with real visitor data.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

Find out what is actually slow.

I map your critical rendering path using real field data. You get a clear answer on what blocks LCP, what causes INP spikes, and where layout shifts originate.

Book a Deep Dive
Perfect YouTube Core Web VitalsCore Web Vitals Perfect YouTube Core Web Vitals