はじめに
「WordPress高速化」シリーズの第8回です。XとInstagramの埋め込みは、記事のずっと下にあっても、ページを開いた直後に合わせて約1.1〜1.6MBを読み込みます。
この記事では、【WordPress高速化】YouTube埋め込みを遅延読み込み(以下「第3回」)と同じ Intersection Observer を使って、投稿の1000px手前に来るまで読み込まないようにします。途中で離れた読者には、XとInstagramの通信が一度も発生しません。表示されたときにずれないように、埋め込みの高さを先に確保する手順もセットで解説します。
WordPress 7.1.4、SWELL 2.19 で確認しています。SWELLの子テーマの functions.php を使います。編集する前に、必ずバックアップを取ってください。
当サイトでは、現在 X と Instagram の埋め込みを使用していませんが、今後使用する可能性があるかもしれないので Localのテスト環境を使って対策を検討していくこととします。
XとInstagramの埋め込みの仕組み
XとInstagramの埋め込みコードは、引用(<blockquote>)と、外部のスクリプトの組み合わせです。
<!-- Xの埋め込みコード -->
<blockquote class="twitter-tweet">…投稿の文章とリンク…</blockquote>
<script async src="https://platform.x.com/widgets.js" charset="utf-8"></script>
<!-- Instagramの埋め込みコード -->
<blockquote class="instagram-media" data-instgrm-permalink="…">…投稿へのリンク…</blockquote>
<script async src="//www.instagram.com/embed.js"></script>スクリプトが読み込まれると、ページの中の blockquote を探して、投稿を表示する <iframe> に置き換えます。最初から iframe のYouTubeと違って loading="lazy" は使えないので、遅らせるのはスクリプトを読み込むタイミングです。
この記事では、どちらも公式の埋め込みコード(投稿の「…」メニューから取得)を、「カスタムHTML」ブロックに貼る形で進めます。WordPressのURL自動埋め込みは、Xは twitter.com のURLだけ、Instagramは対象外のうえ、後で説明する高さの確保もこの形のほうが簡単です。
いつ、どれくらい読み込んでいるか
Localのテスト記事で、本文の下のほうにXとInstagramの投稿を1つずつ埋め込み、スクロールせずに開いたままにして通信を測りました。比較のため、SWELLの「スクリプトの遅延読み込み」(後で説明します)も測っています。
| 方法 | 開いて3秒後 | 開いて8秒後(操作なし) | 埋め込みの近くまでスクロール |
|---|---|---|---|
| 標準(そのまま埋め込む) | 約1.1〜1.6MB | 約1.1〜1.6MB | 約1.1〜1.6MB |
| SWELLの遅延読み込み | 0 | 全部読み込む | 全部 |
| Intersection Observer(この記事) | 0 | 0 | 近づいた投稿の分だけ |
SWELLの遅延読み込みは、読者が操作するか、数秒(初期設定は5秒)たつと、スクロールしていなくても全部読み込みます。Intersection Observerなら、1000px手前に来るまで、何秒たっても0のままです。

遅らせるなら、高さの確保がセット
スクリプトが blockquote を iframe に置き換えると、埋め込みの高さが伸びます(Xはスマホで377px→630〜780px)。標準なら画面の外で伸びるので問題になりませんが、遅らせると読者がスクロールしている途中で、画面の近くで伸びます。
スマホ幅でスクロールしながら、ずれ(CLS)を測った結果です。
| 方法 | ゆっくりスクロール | 速くスクロール |
|---|---|---|
| 標準 | 0 | 0 |
| Intersection Observer・高さの確保なし | 0 | 0.70〜1.01 |
| Intersection Observer+高さの確保 | 0 | 0〜0.006 |
CLSは、0.1以下が「良好」、0.25を超えると「不良」です。遅延読み込みと高さの確保は、セットで行ってください。考え方は、【WordPress高速化】SWELLのCLSをCSSで改善で目次や広告の枠に min-height を付けたのと同じです。

手順:埋め込みに近づいてから表示する
Step1:functions.phpにコードを追加する
子テーマの functions.php に、次のコードを追加します。
// X・Instagramの埋め込みを、画面に近づいてから表示する
add_filter('the_content', function ($content) {
if (is_admin() || is_feed() || wp_is_json_request()) { return $content; }
// 埋め込みに付いてくるスクリプトを外す
$content = preg_replace('#<script[^>]+src="https://platform\.(twitter|x)\.com/widgets\.js"[^>]*></script>#', '', $content);
$content = preg_replace('#<script[^>]+src="(https:)?//www\.instagram\.com/embed\.js"[^>]*></script>#', '', $content);
// スクリプトがまとめて表示しないように、classを変えておく
$content = str_replace('class="twitter-tweet', 'class="lazy-twitter-tweet', $content);
$content = str_replace('class="instagram-media', 'class="lazy-instagram-media', $content);
return $content;
}, 20);
add_action('wp_enqueue_scripts', function () {
if (!is_singular()) { return; }
wp_enqueue_script('embed-lazy', get_stylesheet_directory_uri() . '/js/embed-lazy.js', [], '1.0', ['in_footer' => true, 'strategy' => 'defer']);
});preg_replace(…):本文の中の widgets.js と embed.js の<script>を削除します。Xは、古いplatform.twitter.comと新しいplatform.x.comの両方に一致させていますstr_replace(…):blockquoteのクラス名をlazy-〜に変えます。スクリプトは、ページの中のtwitter-tweet・instagram-mediaをすべて表示してしまうためです。【WordPress高速化】AdSenseを枠ごとに遅延読み込みで、広告の枠のクラス名を変えたのと同じ考え方です- 優先度
20:ブロックやショートコードを展開した後に書き換えるためです
Step2:JavaScriptのファイルを作る
子テーマの js フォルダに、embed-lazy.js というファイルを作ります。
// X・Instagramの埋め込みを、画面に近づいたときに表示する
document.addEventListener('DOMContentLoaded', () => {
const targets = document.querySelectorAll('.lazy-twitter-tweet, .lazy-instagram-media');
if (!targets.length) return;
// スクリプトは1回だけ読み込む
const loaded = {};
const loadScript = (src) => {
if (!loaded[src]) {
loaded[src] = new Promise((resolve) => {
const s = document.createElement('script');
s.src = src;
s.async = true;
s.onload = resolve;
document.body.appendChild(s);
});
}
return loaded[src];
};
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
const el = entry.target;
observer.unobserve(el);
if (el.classList.contains('lazy-twitter-tweet')) {
el.classList.replace('lazy-twitter-tweet', 'twitter-tweet');
loadScript('https://platform.twitter.com/widgets.js')
.then(() => window.twttr.widgets.load(el.parentNode));
} else {
el.classList.replace('lazy-instagram-media', 'instagram-media');
loadScript('https://www.instagram.com/embed.js')
.then(() => window.instgrm.Embeds.process());
}
});
}, { rootMargin: '1000px 0px' });
targets.forEach((el) => observer.observe(el));
});classList.replace(…):近づいた埋め込みだけ、クラス名を元に戻しますtwttr.widgets.load(el.parentNode):指定した要素の中のXの投稿だけを表示しますinstgrm.Embeds.process():まだ表示していないInstagramの投稿を表示しますrootMargin: '1000px 0px':画面の下端から1000px手前に来たら、読み込みを始めます。値の決め方は、後の「rootMarginの値の決め方」で説明します
Step3:埋め込みをdivで囲んで、高さを確保する
「カスタムHTML」ブロックに、埋め込みコードを embed-box というクラスの div で囲んで貼ります。--h-sp にスマホの高さ、--h-pc にPCの高さを書きます。
<div class="embed-box" style="--h-sp: 780px; --h-pc: 820px;">
(ここにXまたはInstagramの埋め込みコードをそのまま貼る)
</div>-- で始まる名前はCSS変数です(【WordPress高速化】目次の高さを見出しの数で自動設定でも使いました)。続けて、外観 > カスタマイズ > 追加CSS に、次のCSSを1回だけ書きます。
/* X・Instagramの埋め込みの高さを確保する */
.embed-box {
min-height: var(--h-sp);
}
@media (min-width: 600px) {
.embed-box {
min-height: var(--h-pc);
}
}幅600pxを境にしているのは、SWELLがそこでスマホとPCのレイアウトを切り替えるためです。
Step4:高さを測る
埋め込みの高さは、投稿の内容と画面の幅によって変わります。今回の投稿では、次のようになりました。
| 画面の幅 | X | |
|---|---|---|
| 360px | 672px | 372px |
| 375px | 641px | 379px |
| 390px | 648px | 385px |
| 412px | 772px | 396px |
| 430px | 780px | 404px |
| 600px以上(PC) | 820px | 488px |
Xは文章の折り返しで高さが変わるので、幅が広いほど高いとは限りません。スマホは360〜430pxの中で一番高い値を --h-sp に、PCの値を --h-pc に書きます。
測るときは、Chromeの検証ツール(F12)でスマホの幅に切り替え、埋め込みが表示されるまでスクロールしてから、「Console」タブで次のコードを実行します。
document.querySelectorAll('.embed-box').forEach((box) => {
box.style.minHeight = '0px';
console.log(Math.ceil(box.getBoundingClientRect().height));
box.style.minHeight = '';
});確保した高さを一時的に外して、埋め込みそのものの高さを上から順に表示します。幅を変えながら測ってください。幅の切り替え方は、【WordPress高速化】CLSの原因を検証ツールで探す方法で解説しています。
一番高い値に合わせるので、幅によっては下に余白ができます(今回のXは幅375pxで約140px)。余白はずれではないので、CLSには影響しません。
Step5:動作を確かめる
- ページのソース(Ctrl+U)で
widgets.jsとembed.jsを検索する → 本文の中の<script>が見つからない - 検証ツールの「ネットワーク」タブを開いて再読み込みする → スクロールしなければ、しばらく待っても
x.com・instagram.comの通信がない - 埋め込みまでスクロールする → 1000px手前で通信が始まり、投稿が表示される
Localで確かめると、幅375px・412px・1366pxのどれでも、投稿は標準と同じ高さで表示され、CLSは0〜0.006でした。
rootMarginの値の決め方
rootMargin は、画面の下端から何px手前で読み込みを始めるかを決める値です。0px なら埋め込みが画面に入った瞬間、1000px なら画面の1000px手前で始めます。

画面に入る前に表示を終えるには、次の距離が必要です。
必要な距離 = 読み込みを始めてから表示が終わるまでの時間 × スクロールの速さ
Localで測ると、表示までの時間は、通信制限なしで約1〜2秒、検証ツールの「高速4G」で約2.5〜3.5秒でした。スクリプト・投稿のデータ・画像を順に取りにいくので、YouTube(第3回は200px)より大きな値が必要です。
スマホ幅で、読みながらの速さ(毎秒500pxと想定)でスクロールしたときの、埋め込みが画面に入ってから表示が終わるまでの遅れです。
| rootMargin | 通信制限なし | 高速4G |
|---|---|---|
| 0px | 0.9〜1.6秒 | 2.6〜3.0秒 |
| 300px | 0.4〜0.9秒 | 2.0〜2.9秒 |
| 600px | 0〜0.3秒 | 1.3〜1.4秒 |
| 1000px | 遅れなし | 0.6〜0.8秒 |
0pxでは、1秒以上、文章とリンクだけの状態が見えます。1000pxなら通信制限なしでは間に合いますが、スマホの回線や速いスクロールでは少し遅れます。すべての条件で間に合わせるには数千px必要で、そこまで広げると、手前で離れた読者にも読み込んでしまいます。
そこで、1000pxを基準にして、間に合わない分は高さの確保で吸収します。高さを確保していれば、表示が遅れても枠の中に文章とリンクが見えるだけで、ずれは起きません(確保しないと、300pxでスマホのCLSが0.33になりました)。
自分のサイトで確かめるときは、「ネットワーク」タブの通信制限で「高速4G」を選び、ふつうに読む速さでスクロールします。表示が遅すぎると感じたら値を大きく、記事の後半まで読まれることが少ないなら値を小さくしてください。
SWELLの「スクリプトの遅延読み込み」との違い
SWELLにも、スクリプトを遅らせる機能があります(SWELL設定 > 高速化 > 遅延読み込み機能 > スクリプトの遅延読み込み)。コードは不要ですが、次の点が違います。
- 操作か数秒で、全部読み込む:マウス・ホイール・タップ・キー操作、または指定の秒数(初期設定は5秒)で、スクロールしていなくてもページの中の埋め込みをすべて読み込みます
- Xは
x.com/widgets.jsを足す:キーワードの初期設定はtwitter.com/widgets.jsで、いまのXの埋め込みコード(platform.x.com/widgets.js)に一致しません。Localでは、x.com/widgets.js,を1行足すと遅延されました - 高さの確保は、こちらでも必要:Step3・Step4は、SWELLの機能で遅らせる場合にも使えます
この記事のコードは本文からスクリプトを削除するので、SWELLの設定と両方使っても、二重に読み込まれることはありません。
注意点
- 投稿を差し替えたら、高さを測り直す:Xの引用ポストや、Instagramの複数枚の投稿は、高さが大きく変わります
- ページの冒頭の埋め込みは遅らせない:開いてすぐ見える位置の埋め込みは、遅らせると表示が遅れて見えます
- キャッシュを削除してから確かめる:SWELLのキャッシュやキャッシュ系のプラグインを使っている場合は、コードを変えたら削除してください
よくある質問・エラー対処
Q. Instagramの埋め込みが、リンクだけの表示になります
→ Instagramは、公開アカウントの投稿しか埋め込めません。非公開アカウントの投稿ではないか確認してください。あわせて、ページのソースで embed-lazy を検索し、JavaScriptが読み込まれているかも確認してください。
Q. 埋め込みブロック(URLを貼る方法)のままでも使えますか
→ コードは動きますが、埋め込みブロックは div で囲めないので、高さを確保できません。カスタムHTMLブロックに貼ってください。
おわりに(まとめ)
Intersection Observerを使えば、XとInstagramの埋め込みを、読者が近づくまで一切読み込まずに済みます。
- ✅ XとInstagramの埋め込みは、画面の外にあっても、ページを開いた直後に合わせて約1.1〜1.6MBを読み込む
- ✅ Intersection Observerなら、1000px手前に来るまで0のまま。近づいた投稿だけを読み込む
- ✅ rootMarginは「表示までの時間 × スクロールの速さ」で考える。1000pxを基準にし、間に合わない分は高さの確保で吸収する
- ✅ SWELLの遅延読み込みは、操作か数秒でスクロールしていなくても全部読み込む。Xは x.com/widgets.js を足す
- ✅ 遅らせると、表示されたときに高さが伸びてCLSが悪化する。min-height で高さを確保する
- ✅ 高さは投稿と画面の幅で変わる。スマホは360〜430pxで一番高い値を使う
この記事が、少しでも誰かのお役に立てれば幸いです。
関連記事
- 【WordPress高速化】HCBを必要な記事だけで読み込む:Highlighting Code BlockのCSSとJSを、コードブロックがある記事だけで読み込む方法(シリーズ第7回)
- 【WordPress高速化】h3まで入れた目次の高さを自動設定:h2とh3を分けて数え、目次の高さを記事ごとに自動で確保する方法(シリーズ第6回)
- 【WordPress高速化】目次の高さを見出しの数で自動設定:PHPで見出しを数えてCSS変数に渡し、目次の高さを記事ごとに自動で確保する方法(シリーズ第5回)
- 【WordPress高速化】AdSenseを枠ごとに遅延読み込み:Intersection Observerで、画面に近づいた広告枠だけを読み込む方法(シリーズ第4回)
- 【WordPress高速化】YouTube埋め込みを遅延読み込み:Intersection Observerの基本と、画面外の動画の読み込みを0KBにした方法(シリーズ第3回)
- 【WordPress高速化】SWELLのCLSをCSSで改善:広告枠などに高さを確保して、CLSを0.14から0.0008に下げた実例(シリーズ第2回)
- 【WordPress高速化】CLSの原因を検証ツールで探す方法:検証ツールで、ずれた場所を見つけて高さを測る方法(シリーズ第1回)
※1回買えば複数サイトで使い回しOK
当サイトの記事で使用したVBAなどのサンプルをDLできます
この記事のサンプルはありません!
ダウンロードページへは下のカードをクリックすればジャンプできます。
よろしければご利用ください!


