Lazy Load YouTube Embed Gutenberg Block
Save as e.g. youtube_facade.php in the WordPress plugins directory and activate.
<?php
/**
Plugin Name: Lazy Load YouTube Embed Block
Plugin URI:
Description: Filters the gutenberg core/embed youtube block content to load a facade until the block is clicked
Version: 1.0
Author: Jem Turner
Author URI: https://jemturner.co.uk
**/
add_filter( 'render_block_core/embed', function( $block_content, $block ) {
// not a youtube embed, dump out original block content
if ( stripos( $block['attrs']['url'], 'youtu' ) === false )
return $block_content;
preg_match( "/^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user|shorts)\/))([^\?&\"'>]+)/", $block['attrs']['url'], $matches );
// if no vid id match, dump out original block content
if ( !isset( $matches[1] ) )
return $block_content;
// get reasonable alt attribute from title or fall back to blank
preg_match( '~title[ ]*=[ ]*["\'](.*?)["\']~is', $block['innerHTML'], $title_matches );
$title_attribute = ( $matches[1] ) ?: '';
// facade magic from https://css-tricks.com/lazy-load-embedded-youtube-videos/
$src_doc = '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/'. $matches[1] .'?autoplay=1><img decoding=async src=https://img.youtube.com/vi/'. $matches[1] .'/hqdefault.jpg><span>▶</span></a>"';
$block_content = str_replace( '<iframe','<iframe '. $src_doc, $block_content );
// wptexturize is replacing the quotes in the srcdoc with htmlentities and breaking things
// so it's disabled here. this does mean you lose smart quotes etc. in the rest of the content
// for pages that contain a youtube video embed, but is that a massive problem? x
remove_filter( 'the_content', 'wptexturize');
return $block_content;
}, 10, 2 );