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
- One number, four waits stacked end to end
- Before the first byte: PHP, MySQL and the cache that might miss
- The hero the browser cannot find yet
- Megabytes in transit: the load duration slice
- Downloaded but not painted: render delay
- Sub-part by sub-part, side by side
- An LCP repair order for WordPress owners
- 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.
| What is happening | Rough target share | |
|---|---|---|
| Time to first byte | The server builds and starts sending the HTML | About 40% |
| Resource load delay | The gap between that first byte and the browser starting to fetch the LCP image | Under 10% |
| Resource load duration | The LCP image itself downloading | About 40% |
| Element render delay | The gap between the image arriving and it appearing on screen | Under 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.
- PicassoImages
- ApolloSite analysis
- AresCompetitor watch
- PrometheusContent holes
- AtlasPage depth and structure
- DelphiAI search visibility
and 12 more agents. Two come with Athena; the rest are monthly add-ons.

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
| Typical WordPress cause | Next.js default | Fix you can make on WordPress | |
|---|---|---|---|
| Time to first byte | PHP, plugins and database queries on every cache miss | Prerendered HTML from a CDN | Full-page caching, a faster host, fewer cache purges |
| Resource load delay | Hero in a CSS background, slider or lazy loader | Hero declared in the template and preloaded | A plain image element, no lazy loading on the hero, a preload |
| Resource load duration | Full-size uploads, background images without srcset | Resized, modern-format images per device | Resize before upload, convert to WebP or AVIF |
| Element render delay | Stacked render-blocking CSS and remote fonts | Component CSS and self-hosted fonts | Critical CSS, local fonts, unused stylesheets removed |
| Text as the LCP element | Font served from another domain with a blocking display rule | next/font with swap and an adjusted fallback | Host fonts locally and preload the one the headline uses |
| Fade-in hero | Slider entrance animation from zero opacity | No animation unless someone writes one | Turn 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
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
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
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
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
Shrink the file
Export the hero at the size it displays, in WebP or AVIF, with smaller versions for phones.
- 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
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
- Theme vs frameworkAstra vs Next.js: A Light Theme, a Heavy Stack and a Custom BuildAstra vs Next.js, row by row: the 2026 AI bundles, the 3-site Pro cap, Elementor and Spectra, real failure modes, and when Astra is still the smart buy.
- New owner, old questionKadence vs Next.js: A Block-First Theme Under New Owners, Against Custom CodeKadence vs Next.js after the Liquid Web shake-up: Kadence Blocks, the new $99 to $499 plans, known issues, and which businesses should stay or move.
- WordPress at its leanestGeneratePress vs Next.js: The Fairest Fight WordPress Can OfferGeneratePress vs Next.js, argued fairly: a sub-10kb theme, a $59 license for 500 sites, the coming template engine, and where a custom build still wins.
- A Customizer theme, weighedBlocksy vs Next.js: A Great Free Theme Against a Site With No Plugins at AllBlocksy vs Next.js compared on 22 rows: the free header builder, Companion and Pro, lifetime licenses, the 2.1.5x regressions and when to stay put.
- The Elementor stack, weighedHello Elementor vs Next.js: The Empty Theme and the Builder That Fills ItHello Elementor vs Next.js on 22 rows: the 6KB vs 30KB claims, Theme Builder dependency, Elementor's real weight, and when the builder is the right call.
- The developer's builderBricks Builder vs Next.js: The Best Case for Staying on WordPress, TestedBricks Builder vs Next.js on 22 rows: clean output, no jQuery, the $599 lifetime plan, 2.4 AI editing and its regressions, and where Next.js still wins.
- Everything in WordPress vs Next.jsSee the section
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.
