Lazyload Iframes
Defer iFrame loading until the embed nears the viewport — either via loading="lazy" or IntersectionObserver.
Metrics
This technique can move up to 33% of LCP's share of the Lighthouse score.
This technique can move up to 33% of TBT's share of the Lighthouse score.
This technique does not move CLS.
This technique can move up to 33% of FCP's share of the Lighthouse score.
This technique can move up to 33% of SI's share of the Lighthouse score.
This technique does not move TTFB.
Each ring is a metric this technique moves.
Impact grade, A+ to D: how much of the Lighthouse score this technique can move. Unaffected: CLS, TTFB.
The Problem
A single YouTube or Google Maps iFrame can fire dozens of sub-requests and execute several hundred kilobytes of third-party JavaScript. When these embeds load at page start they compete with the critical rendering path, blocking the main thread, consuming bandwidth needed for the LCP element, and delaying the page becoming interactive — all for content the user may never scroll to.
Performance Impact
LCP
High
deferred iFrame JavaScript and network requests stop competing with above-the-fold resources
TBT
High
heavy third-party scripts inside iFrames execute after the main thread is free
FCP
Medium
fewer resources competing during the initial render phase
SI
third-party frame resource chains are deferred; their heavy payloads do not slow above-fold visual population
How it works
01
Native loading="lazy" attribute
Adding
loading="lazy"to an<iframe>tag activates the browser’s built-in deferred loading. The browser decides the exact viewport distance threshold. WordPress Core applies this automatically to oEmbed iFrames (YouTube, Vimeo, etc.) since WP 5.7 whenwidthandheightare present.02
Manual iFrames and third-party shortcodes
iFrames added via custom HTML blocks, theme templates, or plugins that do not go through WordPress’s oEmbed pipeline need the attribute added manually. A PHP filter on
the_contentcan injectloading="lazy"into any<iframe>that already has explicit dimensions.03
JavaScript fallback for complex cases
For custom placeholders (e.g. a video poster image that reveals the embed on click — a “facade” pattern) or when browsers need a specific loading threshold, JavaScript with IntersectionObserver swaps a
data-srcvalue intosrcwhen the element approaches the viewport.04
Width and height are non-negotiable
Without explicit dimensions the browser cannot reserve space, causing a layout shift when the iFrame loads. Native
loading="lazy"also only activates reliably when both attributes are present.
HTML — native lazy attribute
<iframe
src="https://www.youtube.com/embed/your-video-id"
width="560"
height="315"
loading="lazy"
title="YouTube video player"
frameborder="0"
allowfullscreen>
</iframe>width and height attributes are required for loading="lazy" to work reliably and to prevent layout shifts.
PHP — add loading="lazy" via filter
<?php
function add_lazy_iframes( $content ) {
if ( is_admin() ) return $content;
return preg_replace(
'/<iframe(?![^>]*loading=)([^>]*)(width=["']\d+["'][^>]*height=["']\d+["']|height=["']\d+["'][^>]*width=["']\d+["'])[^>]*>/i',
'<iframe loading="lazy"$1$2>',
$content
);
}
add_filter( 'the_content', 'add_lazy_iframes', 20 );This adds loading="lazy" only to iFrames that already have both width and height attributes, avoiding empty-dimension iFrames that would cause layout shifts.
Limitations
- An iFrame that is visible on initial load — especially one that is the LCP element — should not be lazy-loaded. Deferring it delays the most important visible content.
- Layout shifts (CLS) occur if
widthandheightattributes are missing — the browser cannot reserve space before the iFrame loads. - Browser thresholds for when lazy loading triggers vary between vendors — content may appear to load slightly earlier or later depending on the browser.
- JavaScript-based solutions do not work when JS is disabled; native
loading="lazy"has no such dependency.
Common Mistakes
Applying loading=”lazy” to an above-the-fold embed
For hero videos or maps that are part of the initial viewport, load eagerly. The lazy attribute is only beneficial for iFrames the user has not yet scrolled to.
Omitting width and height attributes
Always specify explicit dimensions. Without them, native lazy loading may not activate, and the iFrame will cause a CLS hit when it finally loads.
Building custom JavaScript when the native attribute is sufficient
For most WordPress oEmbeds, WP Core already handles it. Check first before adding a plugin or writing a script that duplicates the behaviour.
Need help applying this to your site?
Targeted fixes, not guesswork. We identify which techniques move the needle for your specific WordPress stack.
Start an Engagement