Skip to content

Instantly share code, notes, and snippets.

@mheland
Last active May 16, 2025 07:09
Show Gist options
  • Select an option

  • Save mheland/1fc280248e40cbe08c1f36c20f879cc1 to your computer and use it in GitHub Desktop.

Select an option

Save mheland/1fc280248e40cbe08c1f36c20f879cc1 to your computer and use it in GitHub Desktop.

Revisions

  1. mheland revised this gist Jul 13, 2023. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion YouTube embed in Privacy Enhanced mode
    Original file line number Diff line number Diff line change
    @@ -1 +1,2 @@
    YouTube IFRAME embed for faster page loads in privacy enhanced mode
    YouTube IFRAME embed for faster page loads in privacy enhanced mode
    https://magnushelander.se/youtube-no-cookies-embed-privacy/
  2. mheland revised this gist Jul 13, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion light-yt.js
    Original file line number Diff line number Diff line change
    @@ -44,7 +44,7 @@ function initYouTubeVideos() {
    div.appendChild(videoTitle);

    let playButton=document.createElement('div');
    playButton.setAttribute("class", "play plausible-event-name=VideoPlay");
    playButton.setAttribute("class", "play");
    div.appendChild(playButton);

    div.onclick = function() { labnolIframe(this); };
  3. mheland revised this gist Jul 13, 2023. 1 changed file with 8 additions and 3 deletions.
    11 changes: 8 additions & 3 deletions light-yt.js
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@
    * Light YouTube Embeds by @labnol
    * Credit: https://www.labnol.org/
    * Title from YT oauth by @kmhelander
    * Optimzed by Google's Bard
    * Optimzed by Google Bard
    */


    @@ -36,15 +36,20 @@ function initYouTubeVideos() {
    let div = document.createElement('div');
    div.setAttribute('data-id', videoId);
    div.appendChild(document.createElement('img')).src = '//i.ytimg.com/vi/ID/hqdefault.jpg'.replace('ID', videoId);

    let videoTitle = document.createElement('div');
    videoTitle.setAttribute('class', 'videotitle');
    videoTitle.setAttribute('id', thisPlayerId);
    videoTitle.appendChild(document.createTextNode(''));
    div.appendChild(videoTitle);
    div.appendChild(document.createElement('div').setAttribute('class', 'play'));

    let playButton=document.createElement('div');
    playButton.setAttribute("class", "play plausible-event-name=VideoPlay");
    div.appendChild(playButton);

    div.onclick = function() { labnolIframe(this); };
    playerElements[n].appendChild(div);
    }
    }

    document.addEventListener('DOMContentLoaded', initYouTubeVideos);
    document.addEventListener('DOMContentLoaded', initYouTubeVideos);
  4. mheland revised this gist Jul 13, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion light-yt.js
    Original file line number Diff line number Diff line change
    @@ -41,7 +41,7 @@ function initYouTubeVideos() {
    videoTitle.setAttribute('id', thisPlayerId);
    videoTitle.appendChild(document.createTextNode(''));
    div.appendChild(videoTitle);
    div.appendChild(document.createElement('div').setAttribute('class', 'play plausible-event-name=VideoPlay'));
    div.appendChild(document.createElement('div').setAttribute('class', 'play'));
    div.onclick = function() { labnolIframe(this); };
    playerElements[n].appendChild(div);
    }
  5. mheland revised this gist Jul 13, 2023. 1 changed file with 38 additions and 63 deletions.
    101 changes: 38 additions & 63 deletions light-yt.js
    Original file line number Diff line number Diff line change
    @@ -2,74 +2,49 @@
    * Light YouTube Embeds by @labnol
    * Credit: https://www.labnol.org/
    * Title from YT oauth by @kmhelander
    * Optimzed by Google's Bard
    */

    function labnolIframe(div) {
    var iframe = document.createElement('iframe');
    iframe.setAttribute(
    'src',
    'https://www.youtube-nocookie.com/embed/' + div.dataset.id + '?autoplay=1&rel=0' // No Cookie URL...
    );
    iframe.setAttribute('frameborder', '0');
    iframe.setAttribute('allowfullscreen', '1');
    iframe.setAttribute(
    'allow',
    'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture'
    );
    div.parentNode.replaceChild(iframe, div);
    }

    function initYouTubeVideos() {
    var playerElements = document.getElementsByClassName('youtube-player');
    for (var n = 0; n < playerElements.length; n++) {
    var videoId = playerElements[n].dataset.id;

    // YouTube OEMBED to retrieve title.
    // title, author_name, author_url available in JSON response
    let ytDataUrl = 'https://www.youtube-nocookie.com/oembed?format=json&url=http%3A//youtube.com/watch%3Fv%3D' + videoId;

    // fetch() is async, each player on page must have unique ID
    let thisPlayerId = "playerid-" + n.toString();

    // Fetch the JSON from Youtube and write title in TextNode element - truncated to 30 char
    fetch(ytDataUrl)
    .then(res => res.json())
    .then(out =>
    document.getElementById(thisPlayerId).innerHTML = out.title.substr(0,30) + "....")
    function getYoutubeData(videoId) {
    let ytDataUrl = 'https://www.youtube-nocookie.com/oembed?format=json&url=http%3A//youtube.com/watch%3Fv%3D' + videoId;
    return fetch(ytDataUrl)
    .then(res => res.json())
    .catch(err => { console.log(err) });
    }

    function labnolIframe(youtubePlayer) {
    let iframe = document.createElement('iframe');
    iframe.setAttribute('src', 'https://www.youtube-nocookie.com/embed/' + youtubePlayer.dataset.id + '?autoplay=1&rel=0');
    iframe.setAttribute('frameborder', '0');
    iframe.setAttribute('allowfullscreen', '1');
    iframe.setAttribute('allow',
    'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture');
    youtubePlayer.parentNode.replaceChild(iframe, youtubePlayer);
    }

    function initYouTubeVideos() {
    let playerElements = document.getElementsByClassName('youtube-player');
    for (let n = 0; n < playerElements.length; n++) {
    let videoId = playerElements[n].dataset.id;
    let thisPlayerId = 'playerid-' + n.toString();

    getYoutubeData(videoId)
    .then(out => document.getElementById(thisPlayerId).innerHTML = out.title.substr(0, 40))
    .catch(err => { console.log(err) });

    // Write max size poster image from ytimg.com in an IMG element

    var div = document.createElement('div');
    div.setAttribute('data-id', videoId);
    var thumbNode = document.createElement('img');
    thumbNode.src = '//i.ytimg.com/vi/ID/hqdefault.jpg'.replace(
    'ID',
    videoId
    );
    div.appendChild(thumbNode);

    // Create blank TextNode for title from fetch() - class videotitle

    var videoTitle = document.createElement('div');
    var titleNode = document.createTextNode(' ');
    videoTitle.setAttribute('class', 'videotitle');
    videoTitle.setAttribute('id', thisPlayerId);
    videoTitle.appendChild(titleNode);
    div.appendChild(videoTitle);

    // Create clickable button overlay on poster image
    // Stylesheet sets play button image in .play class

    var playButton = document.createElement('div');
    playButton.setAttribute('class', 'play');
    div.appendChild(playButton);
    div.onclick = function () {
    labnolIframe(this);
    };
    playerElements[n].appendChild(div);
    }
    let div = document.createElement('div');
    div.setAttribute('data-id', videoId);
    div.appendChild(document.createElement('img')).src = '//i.ytimg.com/vi/ID/hqdefault.jpg'.replace('ID', videoId);
    let videoTitle = document.createElement('div');
    videoTitle.setAttribute('class', 'videotitle');
    videoTitle.setAttribute('id', thisPlayerId);
    videoTitle.appendChild(document.createTextNode(''));
    div.appendChild(videoTitle);
    div.appendChild(document.createElement('div').setAttribute('class', 'play plausible-event-name=VideoPlay'));
    div.onclick = function() { labnolIframe(this); };
    playerElements[n].appendChild(div);
    }
    }

    // Wait for content, then create all DIV youtube-player on page
    document.addEventListener('DOMContentLoaded', initYouTubeVideos);
  6. mheland revised this gist Feb 1, 2023. 1 changed file with 11 additions and 4 deletions.
    15 changes: 11 additions & 4 deletions light-yt.js
    Original file line number Diff line number Diff line change
    @@ -24,19 +24,22 @@ function labnolIframe(div) {
    for (var n = 0; n < playerElements.length; n++) {
    var videoId = playerElements[n].dataset.id;

    // YouTube OEMBED to retrieve title.
    // title, author_name, author_url available in JSON response
    let ytDataUrl = 'https://www.youtube-nocookie.com/oembed?format=json&url=http%3A//youtube.com/watch%3Fv%3D' + videoId;

    // fetch() is async, each player on page must have unique ID
    let thisPlayerId = "playerid-" + n.toString();

    // Fetch the JSON from Youtube and write the video title in TextNode element
    // Fetch the JSON from Youtube and write title in TextNode element - truncated to 30 char
    fetch(ytDataUrl)
    .then(res => res.json())
    .then(out =>
    document.getElementById(thisPlayerId).innerHTML = out.title.substr(0,30) + "....")
    .catch(err => { console.log(err) });

    // get the poster image in a IMG element
    // Write max size poster image from ytimg.com in an IMG element

    var div = document.createElement('div');
    div.setAttribute('data-id', videoId);
    var thumbNode = document.createElement('img');
    @@ -46,15 +49,18 @@ function labnolIframe(div) {
    );
    div.appendChild(thumbNode);

    // Create TextNode for title with CSS class videotitle
    // Create blank TextNode for title from fetch() - class videotitle

    var videoTitle = document.createElement('div');
    var titleNode = document.createTextNode(' ');
    videoTitle.setAttribute('class', 'videotitle');
    videoTitle.setAttribute('id', thisPlayerId);
    videoTitle.appendChild(titleNode);
    div.appendChild(videoTitle);

    // Create the play button overlay on poster image
    // Create clickable button overlay on poster image
    // Stylesheet sets play button image in .play class

    var playButton = document.createElement('div');
    playButton.setAttribute('class', 'play');
    div.appendChild(playButton);
    @@ -65,4 +71,5 @@ function labnolIframe(div) {
    }
    }

    // Wait for content, then create all DIV youtube-player on page
    document.addEventListener('DOMContentLoaded', initYouTubeVideos);
  7. mheland revised this gist Jan 31, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion light-yt.js
    Original file line number Diff line number Diff line change
    @@ -48,7 +48,7 @@ function labnolIframe(div) {

    // Create TextNode for title with CSS class videotitle
    var videoTitle = document.createElement('div');
    var titleNode = document.createTextNode('Reading YouTube title..');
    var titleNode = document.createTextNode(' ');
    videoTitle.setAttribute('class', 'videotitle');
    videoTitle.setAttribute('id', thisPlayerId);
    videoTitle.appendChild(titleNode);
  8. mheland revised this gist Jan 31, 2023. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions light-yt.css
    Original file line number Diff line number Diff line change
    @@ -59,11 +59,11 @@
    transform: translate(-50%, -50%); /* Responsive... */
    }

    .youtube-player .videotitle {
    .youtube-player .videotitle {
    position: absolute;
    font-size: 1rem;
    font-size: clamp(0.9rem, 2vw, 1.3rem);
    color: white;
    text-shadow: 1px 1px black;
    left: 10px;
    bottom: 10px;
    top: 10px;
    }
  9. mheland revised this gist Jan 30, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion light-yt.js
    Original file line number Diff line number Diff line change
    @@ -34,7 +34,7 @@ function labnolIframe(div) {
    .then(res => res.json())
    .then(out =>
    document.getElementById(thisPlayerId).innerHTML = out.title.substr(0,30) + "....")
    .catch(err => { throw err });
    .catch(err => { console.log(err) });

    // get the poster image in a IMG element
    var div = document.createElement('div');
  10. mheland revised this gist Jan 30, 2023. 2 changed files with 37 additions and 3 deletions.
    11 changes: 10 additions & 1 deletion light-yt.css
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,10 @@
    /*
    * Light YouTube Embeds by @labnol
    * Credit: https://www.labnol.org/
    * Video title oauth added by @kmhelander
    */

    .youtube-player {
    .youtube-player {
    position: relative;
    aspect-ratio: 16 / 9; /* Modern browsers https://caniuse.com/mdn-css_properties_aspect-ratio */
    width: 100%;
    @@ -58,3 +59,11 @@
    transform: translate(-50%, -50%); /* Responsive... */
    }

    .youtube-player .videotitle {
    position: absolute;
    font-size: 1rem;
    color: white;
    text-shadow: 1px 1px black;
    left: 10px;
    bottom: 10px;
    }
    29 changes: 27 additions & 2 deletions light-yt.js
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,10 @@
    /*
    * Light YouTube Embeds by @labnol
    * Credit: https://www.labnol.org/
    * Title from YT oauth by @kmhelander
    */

    function labnolIframe(div) {
    function labnolIframe(div) {
    var iframe = document.createElement('iframe');
    iframe.setAttribute(
    'src',
    @@ -22,14 +23,38 @@
    var playerElements = document.getElementsByClassName('youtube-player');
    for (var n = 0; n < playerElements.length; n++) {
    var videoId = playerElements[n].dataset.id;

    let ytDataUrl = 'https://www.youtube-nocookie.com/oembed?format=json&url=http%3A//youtube.com/watch%3Fv%3D' + videoId;

    // fetch() is async, each player on page must have unique ID
    let thisPlayerId = "playerid-" + n.toString();

    // Fetch the JSON from Youtube and write the video title in TextNode element
    fetch(ytDataUrl)
    .then(res => res.json())
    .then(out =>
    document.getElementById(thisPlayerId).innerHTML = out.title.substr(0,30) + "....")
    .catch(err => { throw err });

    // get the poster image in a IMG element
    var div = document.createElement('div');
    div.setAttribute('data-id', videoId);
    var thumbNode = document.createElement('img');
    thumbNode.src = '//i.ytimg.com/vi/ID/hqdefault.jpg'.replace(
    'ID',
    videoId
    );
    );
    div.appendChild(thumbNode);

    // Create TextNode for title with CSS class videotitle
    var videoTitle = document.createElement('div');
    var titleNode = document.createTextNode('Reading YouTube title..');
    videoTitle.setAttribute('class', 'videotitle');
    videoTitle.setAttribute('id', thisPlayerId);
    videoTitle.appendChild(titleNode);
    div.appendChild(videoTitle);

    // Create the play button overlay on poster image
    var playButton = document.createElement('div');
    playButton.setAttribute('class', 'play');
    div.appendChild(playButton);
  11. mheland revised this gist Jan 11, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion light-yt.css
    Original file line number Diff line number Diff line change
    @@ -53,7 +53,7 @@
    left: 50%;
    margin-top: 30%;
    position: relative;
    background: url('../images/yt-play-square.png') no-repeat;
    background: url('../images/yt-play5-sq.png') no-repeat;
    cursor: pointer;
    transform: translate(-50%, -50%); /* Responsive... */
    }
  12. mheland revised this gist Jan 9, 2023. No changes.
  13. mheland renamed this gist Jan 9, 2023. 1 changed file with 0 additions and 0 deletions.
  14. mheland revised this gist Jan 9, 2023. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions YouTube light embed
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    YouTube IFRAME embed for faster page loads in privacy enhanced mode
  15. mheland revised this gist Jan 9, 2023. No changes.
  16. mheland revised this gist Jan 7, 2023. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions light-yt.css
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,8 @@
    /*
    * Light YouTube Embeds by @labnol
    * Credit: https://www.labnol.org/
    */

    .youtube-player {
    position: relative;
    aspect-ratio: 16 / 9; /* Modern browsers https://caniuse.com/mdn-css_properties_aspect-ratio */
  17. mheland created this gist Jan 7, 2023.
    55 changes: 55 additions & 0 deletions light-yt.css
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,55 @@
    .youtube-player {
    position: relative;
    aspect-ratio: 16 / 9; /* Modern browsers https://caniuse.com/mdn-css_properties_aspect-ratio */
    width: 100%;
    overflow: hidden;
    background: #000;
    margin: 5px;
    }

    .youtube-player iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 100;
    background: transparent;
    }

    /* Poster image */
    .youtube-player img {
    object-fit: cover;
    display: block;
    left: 0;
    bottom: 0;
    margin: auto;
    max-width: 100%;
    width: 100%;
    position: absolute;
    right: 0;
    top: 0;
    border: none;
    height: auto;
    cursor: pointer;
    -webkit-transition: 0.4s all;
    -moz-transition: 0.4s all;
    transition: 0.4s all;
    }

    .youtube-player img:hover {
    -webkit-filter: brightness(75%);
    }

    /* Play button on poster image */
    .youtube-player .play {
    height: 179px;
    width: 179px;
    left: 50%;
    margin-top: 30%;
    position: relative;
    background: url('../images/yt-play-square.png') no-repeat;
    cursor: pointer;
    transform: translate(-50%, -50%); /* Responsive... */
    }

    43 changes: 43 additions & 0 deletions light-yt.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,43 @@
    /*
    * Light YouTube Embeds by @labnol
    * Credit: https://www.labnol.org/
    */

    function labnolIframe(div) {
    var iframe = document.createElement('iframe');
    iframe.setAttribute(
    'src',
    'https://www.youtube-nocookie.com/embed/' + div.dataset.id + '?autoplay=1&rel=0' // No Cookie URL...
    );
    iframe.setAttribute('frameborder', '0');
    iframe.setAttribute('allowfullscreen', '1');
    iframe.setAttribute(
    'allow',
    'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture'
    );
    div.parentNode.replaceChild(iframe, div);
    }

    function initYouTubeVideos() {
    var playerElements = document.getElementsByClassName('youtube-player');
    for (var n = 0; n < playerElements.length; n++) {
    var videoId = playerElements[n].dataset.id;
    var div = document.createElement('div');
    div.setAttribute('data-id', videoId);
    var thumbNode = document.createElement('img');
    thumbNode.src = '//i.ytimg.com/vi/ID/hqdefault.jpg'.replace(
    'ID',
    videoId
    );
    div.appendChild(thumbNode);
    var playButton = document.createElement('div');
    playButton.setAttribute('class', 'play');
    div.appendChild(playButton);
    div.onclick = function () {
    labnolIframe(this);
    };
    playerElements[n].appendChild(div);
    }
    }

    document.addEventListener('DOMContentLoaded', initYouTubeVideos);