Perfect YouTube Core Web Vitals

Learn how to embed youtube video's without losing PageSpeed

Arjen Karel

Perfect YouTube Core Web Vitals

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

No matter how hard you try, YouTube video's 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 video's without losing PageSpeed

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 naviate 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 Time to interactive have increased by about 1 - 1.5 seconds. Lets 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.

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:

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

Open that url, right click the image and select 'save image as'. After you have downloaded the image resize it to you 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 i-frame that we will populate later.

<div id="ytplaceholder">
   <img class="ytcover"

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:absolute 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 i-frame loads and becomes visible because of the opacity change.

// 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 = = 1;
   ytplaceholder.removeEventListener("mouseover", videolistner);

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

Always show the YouTube video

Lets 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 time-out for simplicity but the requestIdleCallback() method would be great choice as well

var ytplaceholder = document.getElementById ('ytplaceholder'); 

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

ytplaceholder.addEventListener ('mouseover', videolistner);   

// show the YouTube video anyway after 3 seconds

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

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 the interaction-observer to automatically load YouTube video's before they scroll into view. However you want to extend it: the idea stays the same!

lighthouse 100 score

Fix your Core Web Vitals metrics

I am a tech guy and Core Web Vitals consultant. If you need help improving your PageSpeed then I am your guy. I fix technical website issues all around the world!

Core Web Vitals audit   Core Web Vitals support

I am here to help! I can audit your website, consult for your team, fix your PageSpeed or answer any question that you might have about the Core Web Vitals.