Largest Contentful Paint

WordPress LCP vs Next.js: Where the Hero Image Loses Its Seconds

Your LCP score is one number covering four separate waits, and on a WordPress site each wait tends to belong to a different vendor. Here is how to find the one costing you, and how a Next.js build settles all four in code.

October 9, 2026 · 10 min read

The short answer

WordPress usually loses LCP in four places: PHP rendering before the first byte, a hero image the browser finds late (sliders, CSS backgrounds, lazy loading), an oversized image file, and render-blocking CSS and fonts. Next.js serves prerendered HTML, preloads the hero through next/image and self-hosts fonts with next/font. Most WordPress losses can still be fixed with tuning.

On this page
  1. One number, four waits stacked end to end
  2. Before the first byte: PHP, MySQL and the cache that might miss
  3. The hero the browser cannot find yet
  4. Megabytes in transit: the load duration slice
  5. Downloaded but not painted: render delay
  6. Sub-part by sub-part, side by side
  7. An LCP repair order for WordPress owners
  8. When the hero keeps sliding back

One number, four waits stacked end to end

Google defines Largest Contentful Paint as the render time of the largest image, text block or video visible in the viewport, counted from the moment the visitor started loading the page. Its web.dev LCP documentation calls 2.5 seconds or less good and anything over 4.0 seconds poor, judged at the 75th percentile of page loads, with mobile and desktop graded separately. Our Core Web Vitals overview explains how the three metrics fit together. This page takes the first one apart.

The useful part is the breakdown. Google's guide to optimizing LCP splits every LCP time into four sub-parts that happen in order. Shorten any one of them and the total drops. Ignore the wrong one and you can spend a month compressing images on a page whose real problem is a server that takes two seconds to say hello.

Google's four LCP sub-parts and the rough share of the total each should take (per web.dev)
What is happeningRough target share
Time to first byteThe server builds and starts sending the HTMLAbout 40%
Resource load delayThe gap between that first byte and the browser starting to fetch the LCP imageUnder 10%
Resource load durationThe LCP image itself downloadingAbout 40%
Element render delayThe gap between the image arriving and it appearing on screenUnder 10%

Read the targets closely. The two delays are meant to be close to nothing, because they are pure waiting: the file is not moving and the screen is not changing. They are also the two slices a typical WordPress stack inflates most, alongside the time to first byte. The rest of this page goes slice by slice.

Before the first byte: PHP, MySQL and the cache that might miss

An uncached WordPress request is a small construction project. PHP loads WordPress core, then the theme, then every active plugin, runs the database queries the page needs and assembles the HTML from templates and builder data. Only then does the first byte leave the server. Nothing on the visitor's screen can happen before that, which is why Google lists time to first byte as the first slice.

Page caching skips the project by saving finished HTML. It works well for anonymous visitors on a cache hit. The misses are the trouble: the first visitor after a cache purge, logged-in users, WooCommerce cart and checkout pages, and any page the cache has been told to vary by cookie. Plugin updates and content edits often purge the cache, so a busy site spends more of its day rebuilding pages than the owner suspects. Cheap hosting stretches each rebuild, which is a story we tell in full at slow websites on shared hosting.

A Next.js page can be prerendered at build time, or refreshed on a schedule with incremental static regeneration, and the finished HTML sits on a CDN close to the visitor. Time to first byte becomes mostly network distance. To be fair, a Next.js route that renders on every request, for personalized or live data, pays server time too. The difference is that it is a decision made for that one route, not a default for the whole site.

The hero the browser cannot find yet

Browsers read incoming HTML with a fast scanner that spots image addresses and starts fetching them early. Resource load delay grows whenever the hero image is hidden from that scanner. WordPress page designs hide it in several familiar ways.

  • A CSS background. Builder sections love background images. The browser cannot discover one until it has downloaded and parsed the stylesheet that names it, and Google's guide says such images need a preload to be found early.
  • A slider. The first slide often appears only after the slider's script runs, and some sliders lazy-load every slide, including the first.
  • Lazy loading on the hero. WordPress core has added native lazy loading to images since version 5.5. Since 6.3 it skips the first three images by default and marks the likely LCP image with a high fetch priority, but only for images core outputs itself.
  • Script-based lazy loaders. Plugins that park the real address in a data attribute and swap it in with JavaScript hide the image from the scanner entirely.
  • Theme-wide lazy loading. Flatsome's vendor says it uses Smart Lazy Loading on all backgrounds and images, and Bricks can lazy-load images, background images and videos. Useful below the fold, harmful if the hero gets caught.

Google's advice is blunt: never lazy-load the LCP image. Some themes have taken it to heart. WoodMart's Theme Settings > Performance panel includes a Preload LCP Image option, and its documentation warns against lazy-loading the LCP image and against running two lazy-loading systems at once. Our WoodMart speed guide and Flatsome speed guide show where those switches live.

Megabytes in transit: the load duration slice

Once the browser asks for the hero, the question becomes size. WordPress core writes a srcset for images it outputs, offering several widths so a phone can pick a smaller file. That help disappears the moment the hero is a builder background, which usually serves one file to every screen. Add a 4,000-pixel photo uploaded straight from a phone and a mobile visitor downloads a desktop poster to look at a 400-pixel strip. Conversion to WebP or AVIF usually means yet another plugin.

Next.js handles this in its image component. The next/image component resizes images to the widths a device needs and serves modern formats, and the developer declares which image is the hero in the page template. Fairness again: the sizes hint still has to be written correctly, and image optimization runs on the host, which can carry usage costs on some platforms. If you are measuring this slice today, our PageSpeed Insights guide shows where it appears in the report.

The third option

Athena CMS, with AI agents on staff.

Not a theme and not a blank Next.js repo. The content system we put behind every custom site: plain fields, a real preview, every version kept, and AI agents that handle the chores a plugin only nags you about.

and 12 more agents. Two come with Athena; the rest are monthly add-ons.

The Athena CMS editor: plain fields with AI rewrite, a Publish box and revisions

Downloaded but not painted: render delay

The image can be sitting in memory while the screen stays blank. Render delay is the time the browser spends waiting for permission to paint, and on WordPress the permission is usually held by stylesheets. The theme, the builder, the add-on pack and several plugins each put CSS in the page head, and the browser will not paint until it has them. Fonts add a second hold: if the LCP element is a headline and its web font loads with a blocking display rule, the text stays invisible until the file arrives.

There is a quieter culprit too. Google notes that browsers ignore elements with zero opacity when choosing the LCP candidate. A hero that fades in from transparent does not count until the fade makes it visible, so a slider's entrance animation adds its own running time to your score.

Several themes give owners real tools here, and they deserve credit. Divi turns on Critical CSS and Dynamic CSS by default. Avada offers critical CSS generation, non-render-blocking CSS, font-display choices and font preloading. Astra has Load Google Fonts Locally with preloading under Astra > Settings > Performance, and Kadence has the same idea plus Enable CSS Preload under Customizer > General > Performance. Twenty Twenty-Five bundles its fonts locally in theme.json. Storefront, by contrast, still loads Source Sans Pro from Google's servers, which adds a connection to another domain before the text can render.

On a Next.js build, next/font downloads font files at build time, serves them from the site's own domain, preloads them by default and sets font-display to swap, with a size-matched fallback. The CSS is written for the components the site uses, so there is no queue of plugin stylesheets to wait behind.

Sub-part by sub-part, side by side

Where WordPress loses each LCP sub-part, what Next.js does by default, and what a WordPress owner can still fix
Typical WordPress causeNext.js defaultFix you can make on WordPress
Time to first bytePHP, plugins and database queries on every cache missPrerendered HTML from a CDNFull-page caching, a faster host, fewer cache purges
Resource load delayHero in a CSS background, slider or lazy loaderHero declared in the template and preloadedA plain image element, no lazy loading on the hero, a preload
Resource load durationFull-size uploads, background images without srcsetResized, modern-format images per deviceResize before upload, convert to WebP or AVIF
Element render delayStacked render-blocking CSS and remote fontsComponent CSS and self-hosted fontsCritical CSS, local fonts, unused stylesheets removed
Text as the LCP elementFont served from another domain with a blocking display rulenext/font with swap and an adjusted fallbackHost fonts locally and preload the one the headline uses
Fade-in heroSlider entrance animation from zero opacityNo animation unless someone writes oneTurn off the entrance effect on the first slide

One caveat for the Next.js column. The next/image component lazy-loads by default, so the hero has to be marked. In Next.js 16 that is the preload property, which replaced the older priority property, or a high fetch priority. A developer who forgets ships the same lazy hero WordPress owners get scolded for. The difference is that a reviewer can catch it once, in one template, before deploy.

An LCP repair order for WordPress owners

You do not need to leave WordPress to win most of this back. Work in this order, because each step makes the next one easier to measure. The slow LCP troubleshooting guide goes deeper on diagnosis.

  1. 1

    Name the LCP element

    Run your key templates through PageSpeed Insights, which identifies the LCP element. Chrome DevTools' Performance panel breaks its time into the same four phases.

  2. 2

    Fix the first byte

    Confirm full-page caching is on and actually hitting for logged-out visitors. If uncached pages are slow on a quiet server, the host or the plugin count is the problem.

  3. 3

    Put the hero in the HTML

    Replace the slider with one image, or swap the builder background for an image element so the scanner can see it.

  4. 4

    Stop lazy-loading it and preload it

    Exclude the hero from every lazy-loading system, then preload it or give it a high fetch priority. Use your theme's setting if it has one.

  5. 5

    Shrink the file

    Export the hero at the size it displays, in WebP or AVIF, with smaller versions for phones.

  6. 6

    Clear the render path

    Host fonts locally, generate critical CSS if your theme offers it, and stop plugins loading stylesheets on pages that do not use them.

  7. 7

    Wait for field data

    Search Console reflects real visits over a rolling 28 days, so judge the fix on field data, not a single lab run.

Theme-specific versions of these steps live in our speed guides for Divi, Avada, Astra and Kadence. If you would rather hand the job over, our theme speed optimization service does exactly this list.

When the hero keeps sliding back

The repair order works. The trouble is that it describes a state, not a structure. Next quarter someone installs a new slider, the builder update changes how backgrounds are output, a plugin adds its stylesheet to every page, and the hero is late again. Nobody did anything wrong. The four sub-parts simply have four different owners, which is the larger pattern behind why WordPress sites slow down.

A slider is a very expensive way to show one photograph slowly.

On the sites we build, the template owns all four sub-parts and editors cannot undo them. Editors fill in plain fields in Athena CMS, and the build decides how an image becomes a page. Picasso makes sure images are described and sized, never missing, and Argus flags slow pages before Search Console does. For the full side-by-side, see the WordPress vs Next.js comparison center and its speed breakdown; the sibling pages on layout shift and responsiveness cover the other two metrics. Not sure which way to go? Our performance consulting starts with your field data, not a sales pitch.

Questions people ask before they call

Phones get slower processors, slower networks and often the same large hero file. Builder backgrounds rarely offer phone-sized versions, and render-blocking CSS costs more on a slow connection. Google grades mobile and desktop separately, so a desktop pass says little about phones. Our mobile speed guide covers the phone-specific fixes.

Yes, if it is the same image on every load and it is not already in the HTML early. Preload the one image that is actually the LCP element, not a handful of candidates, and make sure no lazy-loading plugin is also handling it. Some themes, like WoodMart, have a setting for it; otherwise a performance plugin or a few lines in a child theme can add the tag.

It fixes the first sub-part for cached pages, and that can be a big slice. It does nothing for a hero hidden in a CSS background, a lazy-loaded first slide or a stack of blocking stylesheets. Many owners install caching, see little change, and install a second one. Measure the four sub-parts first so you know which one you are fixing.

No. It makes the fast path the easy path: prerendered HTML, resized images and self-hosted fonts. A developer still has to mark the hero for preloading, keep the hero file sensible and avoid rendering the main content with client-side JavaScript. Done properly, the result holds because editors cannot change those decisions. See our Next.js development service.

It can, if the first slide is a real image in the HTML, not lazy-loaded, preloaded, correctly sized and shown without a fade-in. At that point the slider is mostly a static image with extra JavaScript attached. Most owners who run that experiment end up keeping the image and dropping the slider.

Keep reading

Free · No obligation

Find out which sub-part is costing you

Send us your URL. We will pull your field data, name your LCP element and tell you which of the four waits to fix first, on WordPress or off it.

Which of these sounds like you? (pick any)

Rather talk now? Call (210) 346-0848.

CallGet a quote