ブログ

pagespeedinsightsで『レンダリングを妨げるリソースの除外』する #4
YOUTUBEの埋め込みコードを遅延ロードする

カトウ
YOUTUBEの埋め込みコードを使用しているページで、『第三者コードの影響を抑えてください』を解消する方法を紹介します。
 
やりたいこと
・再生ボタンが押されるまで<iframe>を読み込まない
・<iframe>を読み込むまでサムネイル画像を表示する
 
おまけ
・YOUTUBE以外(再生ボタンが無い)の<iframe>を遅延ロードさせる
 

デフォルト

HTML
<div class="iframe-content">
	<iframe width="560" height="315" data-src="https://www.youtube.com/embed/vc7LlUtQgNw" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
 

遅延ロード

<iframe>の[src]を空にしておき、再生ボタンが押されると、[data-src]の内容を[src]に入れ、読み込みを開始します。
また、再生ボタンが押されるまで、ページに何も表示されないので、代わりのサムネイル画像と再生ボタンを前面に表示しています。
読み込みが始まると、<iframe>を前面に表示し、IFrame Player APIを使って再生を開始します。
 
おまけで、YOUTUBE以外の<iframe>だった場合は、[data-src]の内容を[src]に入れ、読み込みを開始します。
 
HTML
// YOUTUBEの埋め込みコード
<div class="iframe-content">
	<div class="lazy-iframe">
		// IFrame Player API で再生できるよう『enablejsapi=1』を追加してください
		<iframe loading="lazy" id="iframe-0" width="560" height="315" data-src="https://www.youtube.com/embed/vc7LlUtQgNw?enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
		<img loading="lazy" src="https://img.youtube.com/vi/vc7LlUtQgNw/maxresdefault.jpg" width="560" height="315" />
		<button class="play-btn" type="button">
			<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 512 341.6" xml:space="preserve" class="play-btn-icon"><g>
				<path class="st0" d="M453,332.8c-131.3,11.8-262.6,11.8-394,0c-24.4-2.2-44.3-20.4-48.6-44.5c-13.9-78.7-13.9-156.4,0-235 C14.7,29.2,34.7,11,59,8.8c131.3-11.8,262.6-11.8,394,0c24.4,2.2,44.3,20.4,48.6,44.5c13.9,78.7,13.9,156.4,0,235 C497.3,312.4,477.3,330.6,453,332.8z"></path>
				<path class="st1" d="M335,158.3L222,93c-5.9-3.4-13.3,0.9-13.3,7.7v130.5c0,6.8,7.4,11.1,13.3,7.7l113-65.2 C340.9,170.3,340.9,161.7,335,158.3z"></path>
			</g></svg>
		</button>
	</div>
</div>

// その他のiframe
<div class="iframe-content">
	<div class="lazy-iframe">
		<iframe loading="lazy" id="iframe-1" width="560" height="315" data-src="https://example.zukoo.net/iframe-contents/" frameborder="0"></iframe>
	</div>
</div>
 
CSS
// <iframe>と<img>のサイズを親要素に合わせる
.iframe-content {
	position: relative;
	width: 100%;
	padding: 56.25% 0 0 0;
}
.iframe-content iframe ,
.iframe-content img {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}
.iframe-content img {
	object-fit: cover;
}

// 再生ボタンのスタイル
.play-btn {
	width: 64px;
	height: 43px;
	background-color: transparent;
	border: none;
	cursor: pointer;
	outline: none;
	padding: 0;
	appearance: none;
}
.play-btn-icon {
	width: 64px;
	height: 43px;
	transition: opacity .25s cubic-bezier(0.0,0.0,0.2,1);
}
.play-btn-icon .st0 {
	fill: #212121;
	fill-opacity: .8;
}
.play-btn-icon .st1 {
	fill: #ffffff;
	fill-opacity: 1;
}
// <button>の上にマウスがあるとき、再生ボタンを赤くする
.play-btn-icon:hover .play-btn-icon .st0 {
	fill: #ff0000;
	fill-opacity: 1;
}

// 遅延ロードする<iframe>の上にサムネイルと再生ボタンを重ねる
.lazy-iframe {
	cursor: pointer;
}
.lazy-iframe img {
	z-index: 10;
}
// サムネイルのどこでもクリックできるよう、親要素のサイズに合わせる
.lazy-iframe .play-btn {
	position: absolute;
	z-index: 20;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}
// 再生ボタンを上下左右中央に配置する
.lazy-iframe .play-btn-icon {
	position: absolute;
	z-index: 30;
	top: 50%;
	left: 50%;
	margin-left: -32px;
	margin-top: -21px;
}

// 再生ボタンが押された後は、<iframe>を前面に表示する
.iframe-content .lazy-iframe.is-active iframe {
	z-index: 100;
}
 
JS
(function(window,document){
	var lazyIframe=document.querySelectorAll('.lazy-iframe');
	var lazyYoutube=[];
	var isYoutube=false;
	function _onYoutube(e){
		e.preventDefault();
		var _this=this;
		_this._inPlayBtn.removeEventListener('touchstart',_onYoutube);
		_this._inPlayBtn.removeEventListener('click',_onYoutube);
		_this._inIframe.setAttribute('src',_this._inIframe.dataset.src);
		var youtubePlayer=new YT.Player(_this._inIframe.getAttribute('id'),{
			events:{
				'onReady':function(e){
					e.target.mute(); // 勝手に音が出ないようミュートにしています
					e.target.playVideo();
					_this._lazyYoutube.classList.add('is-active');
				}
			}
		});
	}
	function _youtubeApiIni(){
		// 『JavaScriptを遅延ロードする』で紹介した関数を使用しています
		// https://www.zukoo.net/blog/detail.html?id=269
		window.lazyScriptLib.insertScript('https://www.youtube.com/iframe_api',function(){
			window.YT.ready(function(){
				for(var i=0,l=lazyYoutube.length;i<l;i++){
					var _lazyYoutube=lazyYoutube[i];
					var _inIframe=_lazyYoutube.querySelector('iframe');
					var _inPlayBtn=_lazyYoutube.querySelector('.play-btn');
					_inPlayBtn.addEventListener('touchstart',{
						'_lazyYoutube':_lazyYoutube,
						'_inIframe':_inIframe,
						'_inPlayBtn':_inPlayBtn,
						'handleEvent':_onYoutube
					});
					_inPlayBtn.addEventListener('click',{
						'_lazyYoutube':_lazyYoutube,
						'_inIframe':_inIframe,
						'_inPlayBtn':_inPlayBtn,
						'handleEvent':_onYoutube
					});
				}
			});
		});
	}
	for(var i=0,l=lazyIframe.length;i<l;i++){
		var _lazyIframe=lazyIframe[i];
		var _inIframe=_lazyIframe.querySelector('iframe');
		var _inPlayBtn=_lazyIframe.querySelector('.play-btn');
		if(_inPlayBtn!==null){
			isYoutube=true;
			lazyYoutube.push(_lazyIframe);
		}else{
			// 再生ボタンが無い場合は、読み込みを開始します
			_inIframe.setAttribute('src',_inIframe.dataset.src);
			_lazyIframe.classList.add('is-active');
		}
	}
	if(isYoutube){
		_youtubeApiIni();
	}
})(window,document);