YouTube動画をWordPressサイトに埋め込むと、表示速度の低下やSEOスコアの悪化を引き起こすことがあります。特にモバイルではLCPやCLSに悪影響を及ぼすため注意が必要です。
この記事では、Advanced Custom Fields(ACF)とJavaScriptを使って、YouTube動画をクリック時にモーダル表示する方法を解説します。
目次
実装イメージ
Youtube動画のサムネイルを表示させ、それをクリックすると動画のモーダルウィンドウが表示されます。
iPhone以外なら自動再生されます。
(ちなみにこの動画は、私のアート作品になります)
この実装のSEOメリット
- 初期表示にiframeを読み込まない → ページ高速化
- 画像はloading=”lazy”で遅延読込 → LCP(Largest Contentful Paint)改善
- サムネイルに固定サイズを指定 → CLS(Cumulative Layout Shift)対策
- 動画はクリックされたときだけ再生 → JSでiframeを生成
⸻
実装の概要
- ACFで最大6個までYouTube IDを登録
- PHPでサムネイルを出力(imgは、youtubeのサムネイル画像)
- JavaScriptでクリック時にポップアップでiframeを差し替え再生
⸻
1.ACFフィールドの設定
Youtube動画を6つまで設定できるようにしています。
- フィールド名:youtube_id_post1 ~ youtube_id_post6
- タイプ:テキスト
- 入力値:YouTubeの動画ID(例: dQw4w9WgXcQ)
- 手順:https://www.youtube.com/watch?v=〇〇〇〇〇〇 の〇部分を入力


⸻
2.PHPコード:サムネイル表示+動画再生ボタン出力
<?php
// YoutubeのACFに入力がある時は、Youtubeを表示
for ($i = 1; $i <= 6; $i++) {
$youtube_id_post = get_field('youtube_id_post' . $i);
if ($youtube_id_post):
// Youtubeのサムネイル画像URLを取得
$thumbnail_url = 'https://img.youtube.com/vi/' . $youtube_id_post . '/hqdefault.jpg';
?>
<div class="p-single-youtube p-single-youtube--post<?php echo $i; ?>">
<button class="p-single-youtube__video js-button-youtube" data-video="<?php echo esc_attr($youtube_id_post); ?>" data-start="0">
<img class="youtube-img" src="<?php echo esc_url($thumbnail_url); ?>" alt="<?php the_title_attribute(); ?>" width="720" height="404" loading="lazy" />
</button>
</div>
<?php
endif;
}
?>
⸻
3.JavaScriptでYouTubeiframeを後から挿入
// モーダルYoutube処理
const modalYoutube = () => {
const modal = document.querySelector(".js-modal-youtube");
const modalClose = document.querySelectorAll(
".js-modal-close, .js-modal-bg"
);
const btnMovie = document.querySelectorAll(".js-button-youtube");
const videoIframe = document.querySelector(".p-modal__player iframe");
let videoUrl, videoId, videoStart;
function videoPlay(id, start) {
videoUrl = `https://www.youtube.com/embed/${id}?autoplay=1&rel=0&playsinline=1&start=${start}`;
videoIframe.setAttribute("src", videoUrl);
}
function videoStop() {
videoIframe.setAttribute("src", "");
}
// ボタンをクリックして、モーダルウィンドウを表示
btnMovie.forEach((btn) => {
btn.addEventListener("click", () => {
videoId = btn.getAttribute("data-video");
videoStart = btn.getAttribute("data-start");
modal.style.display = "block";
setTimeout(() => modal.classList.add("is-show"), 10);
videoPlay(videoId, videoStart);
});
});
// モーダルウィンドウを閉じる
modalClose.forEach((btn) => {
btn.addEventListener("click", () => {
modal.classList.remove("is-show");
setTimeout(() => {
modal.style.display = "none";
videoStop();
}, 500);
});
});
};
window.addEventListener("DOMContentLoaded", () => {
modalYoutube();
});
⸻
4.ボタン部分とモーダル部分のCSS
ボタン部分
.p-single-youtube {
position: relative;
&__video {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.11%; // 404/720*100%
display: block;
position: relative;
cursor: pointer;
margin: 40px 0;
img {
position: absolute;
top: 0;
left: 0;
object-fit: cover;
width: 105%; //Youtubeの上下の黒帯を隠すために大きめに設定
height: 100%;
&::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #acacac;
opacity: 0.5;
//乗算
mix-blend-mode: multiply;
}
}
// ボタン部分(擬似クラスで追加)
&::before,
&:after {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 100;
margin: auto;
display: flex;
align-items: center;
justify-content: center;
}
&::before {
content: "再生";
overflow: hidden;
text-indent: -9999px;
width: 6.2rem;
aspect-ratio: 1/1;
border: 1px solid #fff;
border-radius: 50%;
color: transparent;
}
&::after {
content: "";
border-color: transparent;
border-style: solid;
border-left-color: #fff;
border-width: 1.325rem 0 1.325rem 2.1625rem;
width: 0.05rem;
height: 0.05rem;
}
}
}
モーダル部分
/*
* モーダルウィンドウ
*/
.p-modal {
text-align: center;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100%;
z-index: 10000;
display: none;
overflow-y: auto;
-ms-scroll-chaining: none;
overscroll-behavior: contain;
/*クリックアニメーション*/
display: none; //初期値として入れておく
opacity: 0;
transition: opacity 0.5s ease;
/*クリックしたらクラスを追加*/
&.is-show {
opacity: 1;
}
&__bg {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: calc(100vh + 1px);
background: rgba(0, 0, 0, 0.4);
z-index: 1;
}
&__inner {
position: absolute;
top: 50%;
left: 50%;
height: auto;
width: calc(100% - 160px);
max-width: 1037px;
transform: translate(-50%, -50%);
z-index: 2;
@media screen and (max-width: 750px) {
width: 100%;
}
&::after {
content: "";
display: block;
width: 100%;
padding-top: 56.25%;
}
}
&__player {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
iframe,
video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
iframe {
border: none;
}
}
&__close {
width: 29px;
font-size: 40px;
color: #fff;
position: absolute;
top: -44px;
right: -52px;
background-color: transparent;
cursor: pointer;
@media screen and (max-width: 750px) {
top: -50px;
right: 15px;
}
&-icon {
position: relative;
overflow: hidden;
text-indent: -9999px;
display: block;
&::before,
&::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 1px; // 棒の幅(太さ)
height: 30px; // 棒の高さ
background: #fff;
}
&::before {
transform: translate(-50%, -50%) rotate(45deg);
}
&:after {
transform: translate(-50%, -50%) rotate(-45deg);
}
}
}
}
⸻
補足:SEO対策として意識したポイント
対策内容 | 説明 |
---|---|
loading=”lazy” | サムネイル画像の遅延読込でLCP改善 |
iframeを遅延読み込み | JSで挿入することで初期描画を妨げない |
固定サイズ指定 | CLSを防止するため、width と height を明示 |
alt に記事のタイトルを出力 | 画像の代替テキストにもSEO的意味を持たせる |
⸻
まとめ
YouTube動画をページ内に複数埋め込む場合でも、このような「サムネイル+クリック再生型」の実装にすることで、以下のメリットが得られます。
- 高速表示(PageSpeedスコア向上)
- ユーザー体験の向上(遅延読込・安定した表示)
- 動画IDの再利用や更新が簡単(ACF連携)
YouTube埋め込みの最適化は、メディアを多用するサイトでは必須の技術です。WordPressとACFを使うことで、更新性も高く、クライアントにもやさしい構成にできます。