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 );

Comments are closed.