2026年5月20日

2026年5月20日

WordPressのLazy Load(遅延読み込み)を設定する方法

はじめに

Lazy Load(遅延読み込み)はビューポート外の画像やiframeを、ユーザーがスクロールして表示領域に近づいたタイミングで読み込む技術です。WordPress 5.5以降はネイティブの loading="lazy" が自動付与されますが、LCP画像には fetchpriority="high" を設定して優先読み込みが必要です。

症状・原因

  • ページの初期読み込みが遅い
  • PageSpeed Insightsで「スクリーン外の画像を遅延読み込みする」を指摘される
  • ファーストビュー以外の画像も一括で読み込まれている
  • LCP(最大コンテンツフルペイント)の対象画像の表示が遅い

解決手順

ステップ1:WordPress標準のLazy Loadを確認する

// WordPress 5.5以降はデフォルトでloading="lazy"が付与される
// wp_get_attachment_image() の出力例:
// <img src="image.jpg" loading="lazy" ...>

// デフォルト動作の確認
// 最初の画像にはloading="eager"が付与される(WP6.3以降)
// 最初の3画像はeager、それ以降はlazy

// 全画像にlazyを強制したい場合(非推奨)
add_filter('wp_lazy_loading_enabled', '__return_true');

ステップ2:LCP画像にfetchpriority=”high”を設定する

// functions.php

// ヒーロー画像(LCP対象)を優先読み込みに設定
function mytheme_hero_image_priority(string $html, int $attachment_id, string $size): string {
    // ヒーロー画像のIDを指定(またはACF等で動的に取得)
    $hero_image_id = get_theme_mod('hero_image_id');

    if ((int) $attachment_id !== (int) $hero_image_id) {
        return $html;
    }

    // loading="lazy" を削除し、fetchpriority="high"・loading="eager" を追加
    $html = str_replace(' loading="lazy"', '', $html);
    $html = str_replace('<img ', '<img fetchpriority="high" loading="eager" decoding="sync" ', $html);

    return $html;
}
add_filter('wp_get_attachment_image', 'mytheme_hero_image_priority', 10, 3);

// アイキャッチ画像をLCPとして優先読み込み(シングルページ)
function mytheme_singular_thumbnail_priority(string $html): string {
    if (!is_singular()) {
        return $html;
    }

    static $first_thumbnail = true;
    if (!$first_thumbnail) {
        return $html;
    }

    $first_thumbnail = false;
    $html = str_replace(' loading="lazy"', ' loading="eager"', $html);
    $html = str_replace('<img ', '<img fetchpriority="high" ', $html);

    return $html;
}
add_filter('post_thumbnail_html', 'mytheme_singular_thumbnail_priority');

ステップ3:iframeの遅延読み込みを設定する

// functions.php

// コンテンツ内のiframeにloading="lazy"を自動付与
function mytheme_lazy_load_iframes(string $content): string {
    if (!is_singular()) {
        return $content;
    }

    // YouTubeやGoogleマップなどのiframeに遅延読み込みを追加
    $content = preg_replace(
        '/<iframe(?![^>]*\bloading\b)([^>]*)>/i',
        '<iframe loading="lazy"$1>',
        $content
    );

    return $content;
}
add_filter('the_content', 'mytheme_lazy_load_iframes');

ステップ4:Intersection Observer APIでカスタムLazy Loadを実装する

// functions.php

function mytheme_enqueue_lazy_load_script(): void {
    wp_add_inline_script('jquery', mytheme_get_lazy_load_js());
}
add_action('wp_footer', 'mytheme_enqueue_lazy_load_script');

function mytheme_get_lazy_load_js(): string {
    return <<<'JS'
(function() {
    // data-src 属性を持つ要素をLazy Loadする
    const lazyImages = document.querySelectorAll('img[data-src]');
    if (!lazyImages.length) return;

    const observer = new IntersectionObserver(function(entries) {
        entries.forEach(function(entry) {
            if (!entry.isIntersecting) return;
            const img = entry.target;
            img.src = img.dataset.src;
            if (img.dataset.srcset) {
                img.srcset = img.dataset.srcset;
            }
            img.removeAttribute('data-src');
            observer.unobserve(img);
        });
    }, { rootMargin: '200px 0px' }); // 200px手前で読み込み開始

    lazyImages.forEach(function(img) { observer.observe(img); });
})();
JS;
}
// テンプレートでdata-src属性を使ったLazy Load画像出力
function mytheme_lazy_image(int $attachment_id, string $size = 'large'): string {
    $src    = wp_get_attachment_image_url($attachment_id, $size);
    $srcset = wp_get_attachment_image_srcset($attachment_id, $size);
    $alt    = get_post_meta($attachment_id, '_wp_attachment_image_alt', true);

    return sprintf(
        '<img data-src="%s" data-srcset="%s" alt="%s" class="lazy" width="%s" height="%s">',
        esc_url($src),
        esc_attr($srcset ?: ''),
        esc_attr($alt),
        '800',
        '600'
    );
}

ステップ5:動画のLazy Loadを設定する

<!-- 動画のpreload属性をnoneに設定(自動バッファリングを防ぐ) -->
<video
    src="video.mp4"
    preload="none"
    poster="thumbnail.jpg"
    loading="lazy"
    controls>
</video>

<!-- YouTubeはfacade(軽量サムネイル)で代替 -->
<!-- lite-youtube-embed ライブラリを使用 -->
<lite-youtube videoid="dQw4w9WgXcQ"></lite-youtube>

注意事項

  • LCP対象の画像(ファーストビューのメイン画像)には絶対に loading="lazy" を使わないでください。LCPスコアが悪化します
  • fetchpriority="high" はページ内に1つだけにするのが理想です。複数設定すると優先度の意味がなくなります
  • Intersection Observer は古いブラウザ(IE)では動作しません。loading="lazy" の方がブラウザサポートが広いため、こちらを優先してください

まとめ

WordPress 5.5以降の loading="lazy" は自動付与されるので追加設定は不要です。重要なのはLCP画像に fetchpriority="high"loading="eager" を設定すること。the_content フィルターでiframeに loading="lazy" を付与し、カスタムコンポーネントには Intersection Observer でビューポート近傍での読み込みを実装します。

お気軽にご相談ください

お見積りへ お問い合わせへ