Elementor LCP Fix — Why Your Hero Image Is Slowing You Down
Elementor's background-image pattern fails LCP attribution. Here's the fix without rebuilding your template.
Elementor is the dominant WordPress page builder, and it has a persistent LCP problem that shows up on nearly every site built with it: the hero image is set as a CSS background-image, which the browser can't preload.
This isn't an Elementor bug exactly — it's a fundamental limitation of how CSS background images work. The browser has to download and parse the CSS, evaluate which element the background applies to, and then queue the image download. By the time the image request starts, the LCP clock has already been running for 500–800ms. If your hero is a full-width background image in an Elementor section, this is your LCP problem.
Why Background Images Fail LCP Preloading
When the browser parses your HTML, it scans for resources it can download early: images in <img> tags, fonts with rel="preload", scripts in <head>. This early scan is called the preload scanner.
CSS background images don't appear in the preload scan because they're defined in stylesheets, not HTML. The browser can't discover them until:
- The HTML is parsed and the stylesheet is requested
- The stylesheet downloads
- The CSS is parsed and applied to the DOM
- The computed style for the element reveals the background-image URL
- The image download begins
That's four sequential steps before the image even starts downloading. For an LCP element, this sequence is a significant performance penalty.
<img> tags, by contrast, are discovered in the first HTML parse pass and can start downloading immediately.
Diagnosis: Is Your LCP a Background Image?
Run your URL in PageSpeed Insights. In the Diagnostics section, look for:
- "Largest Contentful Paint image was not preloaded"
- An element path like
section.elementor-section > div.elementor-background-overlay
If the LCP element path points to a section or division with elementor-section in the class, it's almost certainly a background image. You can confirm by right-clicking the hero in your browser, choosing Inspect, and looking at the CSS panel for a background-image property on the element.
Fix 1: Preload the Background Image in <head>
The most direct fix is a manual preload link. Add it as high as possible in <head>, before stylesheets:
<link
rel="preload"
as="image"
href="https://yoursite.com/wp-content/uploads/2026/05/hero-bg.jpg"
fetchpriority="high"
/>
In WordPress, add this via functions.php using wp_head with priority 1:
<?php
add_action( 'wp_head', function() {
// Replace with your actual hero image URL
$hero_url = 'https://yoursite.com/wp-content/uploads/2026/05/hero-bg.jpg';
echo '<link rel="preload" as="image" href="' . esc_url( $hero_url ) . '" fetchpriority="high" />' . PHP_EOL;
}, 1 );
This tells the browser to begin downloading the image as soon as <head> is parsed — effectively the same as an <img> tag for preload purposes.
Fix 2: Switch to an <img> Tag for the Hero
If you can modify the template without breaking the design, replacing the background-image section with an actual <img> tag is the cleanest fix. Elementor Pro's Image widget places a real <img> element in the DOM, which the preload scanner finds automatically.
The trade-off: CSS background images cover their container and scale responsively with background-size: cover, which is harder to replicate with <img>. For most hero layouts, you can achieve the same effect with CSS:
.hero-wrapper {
position: relative;
overflow: hidden;
}
.hero-image {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
}
Then in Elementor, use an HTML widget or a custom template to output:
<div class="hero-wrapper">
<img
class="hero-image"
src="/wp-content/uploads/2026/05/hero.jpg"
alt="Your hero description"
fetchpriority="high"
loading="eager"
width="1920"
height="1080"
/>
<!-- Hero content overlaid -->
</div>
This gets you the same visual result with a preload-scannable <img> element.
Fix 3: Inline Critical CSS for the Hero Section
If your LCP issue is partly caused by render-blocking stylesheets (common with Elementor's large CSS files), inlining the critical CSS for the hero section eliminates the render-blocking delay:
With Perfmatters or WP Rocket, enable Critical CSS Generation or Eliminate Render-Blocking Resources. These tools identify CSS rules needed for above-the-fold rendering and inline them in <head>, deferring the rest.
Without a plugin, you can manually identify critical CSS using Chrome DevTools > Coverage tab, which shows which CSS rules are used for the initial render vs. loaded lazily.
The Font LCP Problem
Elementor sites sometimes have LCP caused not by an image but by the H1 or hero heading text — specifically, text that renders blank until a custom font loads.
If PSI identifies your LCP element as text content (an h1, p, or span), the problem is font loading. The fix:
@font-face {
font-family: 'YourFont';
src: url('/fonts/yourfont.woff2') format('woff2');
font-display: swap; /* Show fallback font immediately, swap when loaded */
}
font-display: swap makes the browser show system font text immediately, then swap to your custom font when it loads. LCP captures the initial text render, not the font swap — so the LCP score improves even if the user sees a brief font change.
Add a preload for the font file too:
<link
rel="preload"
href="/fonts/yourfont.woff2"
as="font"
type="font/woff2"
crossorigin
/>
Plugin Solutions for Elementor LCP
Perfmatters handles Elementor LCP well. Enable:
- LCP Preload Image (automatically detects the LCP element and adds the preload)
- Delay JavaScript Execution (defers Elementor's JS until interaction)
- Critical CSS (inlines above-fold styles)
WP Rocket works similarly. The LCP Image Preloading feature, introduced in WP Rocket 3.15, uses PSI data to automatically preload the right image. This is the most automated option — it handles URL matching and CDN prefixes automatically.
Checking Your Score After Fixes
After applying any of these fixes, re-run PageSpeed Insights and look specifically at:
- LCP value — should move toward under 2.5s
- Opportunity: "Preload Largest Contentful Paint image" — should disappear if your preload is working
- Opportunity: "Eliminate render-blocking resources" — this is the CSS/font issue, separate from the background-image problem
For the full breakdown of LCP scoring and what counts as the LCP element, see What Is a Good LCP Score?. If WordPress's automatic lazy loading is also affecting your Elementor site, see WordPress Lazy Loading LCP Fix.
For Shopify CLS issues, which often show up alongside LCP problems in multi-platform shops, see How to Fix CLS on a Shopify Theme. The Core Web Vitals guide covers all three metrics and how they factor into rankings.