<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Responsive, Privacy Friendly YouTube Embed Demo (Full Source)</title>
</head>
<body>
<h1>Responsive, Privacy Friendly YouTube Embed Demo (Full Source)</h1>
<!-- ******** Better YouTube Embed Implementation ******** -->
<div class="youtube-embed"
data-thumb-url="my-thumbnail.jpg"
data-video-id="L-mMmNX75mk"
data-show-play-button="true">
</div>
<!-- ******** End Better YouTube Embed Implementation ******** -->
<p style="padding:0.5rem; border:dashed 1px grey; margin-left:1rem; margin-right:1rem;">
📣 You are viewing the <strong>full source</strong> version of this
demo, which shows how it all works. If you would like a download
you can implement on your website, you may prefer to
<a href="../?docid=better-youtube-embeds-implementation" target="_parent">
Visit the Implementation Version
</a>
of this demo.
</p>
<p>
By default, YouTube embeds have a few, what you might call "issues":
</p>
<ol>
<li>
Don't resize good with the browser window
</li>
<li>
Have an annoying overlay which may block your important
thumbnail elements
</li>
<li>
Set various cookies and localStorage, even if the visitor
doesn't interact with the video
</li>
</ol>
<p>
<strong>#1</strong> and <strong>#2</strong> is completely solved by
this demo by loading only a thumbnail image and play button from
our own website. The thumbnail image and button is styled by our
own CSS to be responsive, and coded to switch to the YouTube iframe
only if the visitor clicks the thumbnail.
</p>
<p>
<strong>#3</strong> is as solved as much as reasonably possible by
this demo due to the fact the iframe is only loaded when the
visitor clicks the thumbnail. This means if the visitor is browsing
your site passively, e.g. doesn't click the thumbnail, no YouTube
will be loaded at all. If they DO click, the YouTube embed/iframe
is then swapped in (the nocookie variant). This does set some
cookies/localstorage, however there's not much we can do about that
if we want to have a YouTube embed on our site. But at least we've
improve the privacy on our site as much as possible.
</p>
<!-- ******** YouTube Embed StyleSheet ******* -->
<style>
.youtube-embed
{
position:relative;
width:560px;
max-width:100%;
margin-left:auto;
margin-right:auto;
margin-top:0;
margin-bottom:1rem;
aspect-ratio: 16 / 9;
}
.youtube-embed-thumbnail
{
background-size:100% 100%;
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
cursor:pointer;
display:flex;
align-items:center;
justify-content:center;
}
.youtube-embed-play-button
{
background-image:url("play-button.png");
background-size:200% 100%;
background-position:0 0;
background-repeat:no-repeat;
width:8%;
height:15%;
contain:fit;
}
.youtube-embed-thumbnail:active .youtube-embed-play-button,
.youtube-embed-thumbnail:hover .youtube-embed-play-button
{
background-position:100% 0;
}
.youtube-embed-iframe
{
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
}
</style>
<!-- ******** End YouTube Embed StyleSheet ******* -->
<!-- ******** YouTube Embed Script ******* -->
<script>
let scYoutubeEmbeds = {};
// init. insert stylesheet into <head>. loop all <div class="youtube-embed">s,
// and init them
scYoutubeEmbeds.init = function()
{
let youtubeEmbeds = document.querySelectorAll( ".youtube-embed" );
for( let i = 0; i < youtubeEmbeds.length; i++ )
{
// set embed html to thumbnail div
youtubeEmbeds[ i ].innerHTML = `
<div class="youtube-embed-thumbnail">
</div>
`;
// set thumbnail div background image to url from embed div data-thumb-url
let thumbDiv = youtubeEmbeds[ i ].querySelector( ".youtube-embed-thumbnail" );
let thumbURL = youtubeEmbeds[ i ].getAttribute( "data-thumb-url" );
thumbDiv.style.backgroundImage = "url(" + thumbURL + ")";
// register click event to onThumbnailImageClick below
thumbDiv.addEventListener( "click", scYoutubeEmbeds.onThumbnailImageClick );
// if embed div data-thumb-url says show play button, create and append it in
if( youtubeEmbeds[ i ].getAttribute( "data-show-play-button" ) == "true" )
{
thumbDiv.innerHTML = `
<span class="youtube-embed-play-button">
</span>
`;
let playButton = thumbDiv.querySelector( ".youtube-embed-play-button" );
}
}
}
// click event listener. remove image and replace with youtube video from
// youtube
scYoutubeEmbeds.onThumbnailImageClick = function( e )
{
// get youtube embed <div>
let youtubeEmbed = e.currentTarget.parentNode;
// get video ID from div
let videoID = youtubeEmbed.getAttribute( "data-video-id" );
// remove click event listener (since we loading video now)
youtubeEmbed.removeEventListener( "click", scYoutubeEmbeds.onDivclick );
// prep youtube embed params
let paramsStr = "";
paramsStr += "?rel=0"; // as of 2025, if 0, will show related videos from same channel, if 1, shows whatever youtube decides
paramsStr += "&controls=1"; // show or hide the youtube control bar (play, time slider, etc)
paramsStr += "&showinfo=0"; // as of 2025, this parameter is ignored. is used to show/hide the video title at the top
paramsStr += "&modestbranding=1"; // 1=hide youtube logo in the title bar, 0 = don't
paramsStr += "&autoplay=1"; // video will auto play (in our situation, this means it will actual play after visitor clicks play)
paramsStr += "&loop=1"; // video will start over once reaches the end. nice!
paramsStr += "&playlist=" + videoID; // this is required to make the loop "1" parameter work
// prep youtube iframe html
let html = `
<iframe class="youtube-embed-iframe"
width="560"
height="315"
src="https://www.youtube-nocookie.com/embed/` + videoID + paramsStr + `"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen
></iframe>
`;
// load video by putting it into the div
youtubeEmbed.innerHTML = html;
}
</script>
<!-- ******** End YouTube Embed Script ******** -->
<!-- ******** Init YouTube Embed Script! ******** -->
<script>scYoutubeEmbeds.init();</script>
<!-- ******** End Init YouTube Embed Script! ******** -->
</body>
</html>