Core Web Vitals

Why Is LCP Slow? A Root-Cause Framework

September 15, 2026 webperflab_admin 13 min read

Core Web Vitals

A slow Largest Contentful Paint does not automatically mean the LCP image is too large. LCP can be delayed before the browser discovers the resource, while that resource is loading, after it has finished loading, or even before the browser receives the first byte of HTML.

The first task is therefore not optimization. It is determining which part of the LCP timeline is responsible.

A useful LCP investigation decomposes the metric into server response, resource load delay, resource load duration and element render delay. Once the dominant stage is known, the investigation can move to the correct layer instead of applying generic fixes.

Why is LCP slow?

LCP can be slow because the initial HTML response arrives late, the LCP resource is discovered too late, the resource downloads slowly, or the browser cannot render it promptly because of CSS, JavaScript or main-thread work. The correct fix depends on which part of the LCP timeline is actually responsible.

Poor LCP Is a Symptom, Not a Root Cause

LCP is the final timing outcome of several stages.

A poor value tells you that the largest qualifying visible content appeared later than desired. It does not identify why.

POSSIBLE CAUSE

Server response is late

The browser cannot begin processing the document until the HTML response starts arriving.

POSSIBLE CAUSE

Resource discovery is late

The browser receives HTML but cannot request the LCP resource until a later dependency reveals it.

POSSIBLE CAUSE

Resource loading is slow

The request starts early, but the bytes take too long to arrive.

POSSIBLE CAUSE

Rendering is late

The resource is already available, but CSS, JavaScript, main-thread work or application state delays paint.

“Optimize the image” is not a diagnosis. It is only relevant when evidence shows image delivery is a meaningful part of the LCP bottleneck.

For the broader metric context, see Core Web Vitals.

First Identify the Actual LCP Element

Before diagnosing LCP, confirm which element the browser is actually reporting as the LCP candidate.

Depending on the page and browser behavior, the LCP element may be:

  • an image;
  • a text block;
  • a CSS background image that qualifies for LCP;
  • a video poster;
  • another eligible content element.

Do not assume the visually largest hero is automatically the LCP element.

The candidate may also change during page load as larger eligible content is rendered.

Diagnosis begins with the measured LCP candidate, not the element that merely looks largest in the design.

See identify the LCP element for the dedicated guide.

Break LCP Into Its Delay Components

The current web.dev diagnostic model breaks LCP into four timing subparts:

VISUAL 1 — LCP Timing Breakdown

TTFB → Resource Load Delay → Resource Load Duration → Element Render Delay → LCP

1. Time to First Byte

Time from navigation start until the browser receives the first byte of the HTML document response.

2. Resource Load Delay

Time between TTFB and the moment the browser starts loading the LCP resource.

3. Resource Load Duration

Time required to transfer the LCP resource itself.

4. Element Render Delay

Time between the LCP resource finishing and the LCP element actually rendering.

If the LCP element does not require a separate network resource—for example, some text-based LCP cases—the resource load delay and resource load duration can be zero.

This decomposition matters because shortening one stage does not always improve total LCP if the saved time simply shifts into another stage.

Cause 1: The Server Response Arrives Too Late

If the initial HTML arrives late, every downstream browser action begins later.

Possible contributors include:

  • origin processing;
  • cache MISS behavior;
  • application execution;
  • database work;
  • upstream services;
  • CDN-to-origin latency;
  • network conditions.

A high document response time should not immediately become:

Upgrade the hosting.

The correct next step is to determine where the response delay actually occurs.

If HTML delivery is already the dominant bottleneck, frontend-only LCP changes may have limited impact until the response path is addressed.

For the broader diagnosis method, see the root-cause performance investigation. For WordPress-specific cases, see diagnose high WordPress TTFB.

Cause 2: The LCP Resource Is Discovered Too Late

The browser cannot request a resource before it knows that resource exists.

An LCP resource may be discovered late when it is:

  • inserted by JavaScript;
  • referenced through a stylesheet;
  • hidden behind another dependency;
  • lazy-loaded unnecessarily;
  • introduced after client-side rendering;
  • created only after application logic runs.
VISUAL 4 — Request Discovery Chain

HTML → CSS / JavaScript / Framework Work → LCP Resource

The longer the dependency chain before discovery, the later the request can begin.

This is why an image can be well compressed and still produce poor LCP: the browser may simply learn about it too late.

See late LCP discovery for the dedicated investigation.

Cause 3: The LCP Resource Takes Too Long to Load

If the browser discovers the LCP resource early but the request itself takes too long, the relevant stage is resource load duration.

Evidence may point toward:

  • resource size;
  • image dimensions or responsive candidate selection;
  • network throughput;
  • resource origin;
  • CDN behavior;
  • caching;
  • connection cost;
  • network contention;
  • request priority.

This is where image optimization may become relevant—but only if the actual LCP resource is an image and transfer duration is meaningfully contributing to total LCP.

Do not automatically convert every LCP image to another format and call the problem solved. First prove that resource load duration is the stage that needs improvement.

Responsive images matter

The resource actually downloaded by the browser may be selected from srcset and sizes.

Diagnosis should therefore inspect the network request that was actually made, rather than assuming the CMS-visible image URL is the resource users received.

Cause 4: The Resource Loads but Rendering Happens Late

One of the most important LCP patterns is:

The resource finishes loading early, but the LCP paint happens much later.

That gap is element render delay.

Possible causes include:

  • render-blocking stylesheets;
  • synchronous scripts;
  • JavaScript execution;
  • main-thread contention;
  • the element not yet existing in the DOM;
  • client-side rendering or hydration;
  • the element being hidden until application state changes;
  • style calculation and layout;
  • font-related rendering behavior for text LCP;
  • animation or delayed visibility.
VISUAL 3 — Fast Resource vs Late Paint

Resource Request → Resource Complete ─────────────→ LCP Paint
                                ↑ Element Render Delay ↑

When this pattern exists, compressing the resource further may reduce download time without materially improving total LCP.

For the dedicated path, see LCP image loads fast but LCP is still slow.

How the Network Waterfall Helps Diagnose LCP

A network waterfall helps establish the order of events.

For LCP diagnosis, it can answer questions such as:

  • When did the HTML response begin?
  • When did the LCP resource request start?
  • Was the request discovered early or late?
  • How long did the transfer take?
  • Did another network dependency need to complete first?

The waterfall should not be treated as the entire diagnosis. It explains network timing, but it may not explain why paint occurred late after the network became quiet.

See read the network waterfall for the deeper workflow.

Use the Request Initiator to Find Late Discovery

If the LCP request begins late, the next question is:

What caused this request to start?

The request initiator can help identify whether the request came from:

  • the HTML parser;
  • CSS;
  • JavaScript;
  • a framework;
  • a tag manager;
  • another dependency.

This can turn a vague finding such as “the LCP image starts late” into a stronger explanation:

The browser cannot discover the LCP resource until a stylesheet, script or application dependency exposes it.

When You Need a Performance Trace

A waterfall is excellent for request timing.

It becomes less sufficient when the network looks healthy but the LCP element still renders late.

A Performance Trace becomes useful when:

  • the main thread is busy;
  • JavaScript execution occurs before paint;
  • style or layout work is significant;
  • the resource is complete but rendering is delayed;
  • client-side rendering controls when the element appears.

The trace provides evidence about browser work that a request waterfall alone cannot show.

Why Main-Thread Work Can Delay LCP

LCP is not purely a network metric.

The browser still has to perform work before pixels can appear.

If the main thread is occupied by:

  • JavaScript execution;
  • long tasks;
  • style calculation;
  • layout;
  • other rendering work;

the LCP element may wait even though its resource has already arrived.

Network complete does not mean rendering complete.

Does Preloading the LCP Resource Help?

Preload is not a universal LCP fix.

It can be useful when:

  • the resource is genuinely critical;
  • the browser needs it early;
  • normal discovery happens too late.

But preload may provide little benefit—or introduce new problems—when:

  • the resource is already discovered early;
  • the wrong responsive image candidate is preloaded;
  • the browser performs duplicate or unnecessary work;
  • too many resources are preloaded;
  • the real bottleneck is render delay rather than discovery.

Before adding preload, prove that resource load delay is a meaningful part of the LCP timeline.

See preload the LCP image for the focused guide.

Lazy Loading and LCP

An above-the-fold LCP resource should not be unnecessarily delayed by lazy-loading behavior.

But that does not mean lazy loading should be disabled site-wide.

The correct scope is the resource that is critical to the initial viewport.

If an LCP resource is hidden behind JavaScript-based lazy loading or receives intentionally delayed loading behavior, investigate whether that delay is responsible for late request start.

CSS Background Images and LCP Discovery

A critical image referenced through CSS may be discovered differently from an image URL available directly in the initial HTML.

The browser may need to download and process the relevant stylesheet before it can discover the image.

This can increase resource load delay depending on the implementation.

That pattern belongs in the late LCP discovery investigation rather than a generic image-compression workflow.

Client-Side Rendering Can Delay LCP

If the LCP element only appears after:

  • framework execution;
  • hydration;
  • an API response;
  • component mount;
  • application state initialization;

the asset itself may be relatively small and still appear late.

The bottleneck is then not simply transfer size. The browser may be waiting for application work before the element can exist or become visible.

LCP Candidate Changes During Page Load

The browser can update the LCP candidate as larger eligible content is rendered.

This matters because an optimization can change which element becomes the final candidate.

After making a change, confirm that:

  • the expected element is still the actual LCP candidate;
  • the timing being compared belongs to the same user-visible content;
  • the improvement did not merely move LCP attribution to a different element.

Field LCP vs Lab LCP

Lab LCP and field LCP can differ because the environments are different.

Real users vary by:

Device capability
Network conditions
Cache state
Geography
Template and content
User state
Third-party behavior
Traffic distribution

Lab testing is useful for controlled reproduction and diagnosis. Field data shows what actual users experience across production conditions.

For the broader distinction, see Lighthouse vs Core Web Vitals.

A Practical LCP Diagnostic Framework

Identify the actual LCP element

Confirm the browser-reported candidate before optimizing.

Measure document response

Determine whether TTFB is already consuming a significant part of the LCP timeline.

Find when the LCP resource is discovered

Compare TTFB with the request start and inspect the initiator.

Measure resource load duration

Determine whether transfer time is materially contributing to LCP.

Compare resource completion with LCP paint

A large gap indicates render delay rather than transfer delay.

Inspect main-thread and rendering activity

Use a trace when network timing does not explain the delay.

Form a root-cause hypothesis

State which stage appears responsible and what evidence supports it.

Confirm with evidence

Look for supporting and contradicting evidence before treating the hypothesis as fact.

Fix the responsible layer

Apply the smallest targeted change that addresses the identified stage.

Repeat and verify

Re-test under comparable conditions and check for regressions.

LCP Symptom → Evidence → Likely Category

LCP symptom Evidence Likely category Next investigation
HTML arrives late Document timing, TTFB, cache status Server response / TTFB Server, application, cache or origin path
LCP request starts late Waterfall, initiator Resource load delay / discovery Late discovery and dependency chain
Request starts early but finishes late Network timing, transfer size, resource selection Resource load duration Resource delivery, network, CDN, candidate selection
Resource finishes early but LCP is late Performance trace, DOM/render timing Element render delay Main thread, CSS, JavaScript, rendering

A Practical LCP Diagnostic Decision Tree

VISUAL 2 — LCP Root-Cause Decision Tree

TTFB → Discovery → Load → Render

IS THE DOCUMENT RESPONSE LATE?
│
├─ YES
│  └─ Investigate TTFB → server → application → cache → origin
│
└─ NO
   ↓
DOES THE LCP RESOURCE START LATE?
│
├─ YES
│  └─ Investigate discovery → initiator → dependency chain
│
└─ NO
   ↓
DOES THE RESOURCE DOWNLOAD TAKE TOO LONG?
│
├─ YES
│  └─ Investigate size → network → CDN → resource selection
│
└─ NO
   ↓
IS THE RESOURCE COMPLETE WELL BEFORE LCP?
│
├─ YES
│  └─ Investigate render delay → main thread → CSS → JS → application state
│
└─ NO
   └─ Continue resource / network investigation

Common LCP Diagnosis Mistakes

Assuming LCP is always the hero image

Confirm the actual candidate first.

Only compressing the image

Compression helps only when transfer duration is a meaningful bottleneck.

Preloading every hero asset

Preload should follow evidence of late discovery or insufficient priority.

Ignoring TTFB

A late document can delay the entire loading path.

Ignoring request start time

A fast download can still start far too late.

Looking only at file size

File size does not explain discovery or render delay.

Ignoring the initiator

The initiator often reveals why the request starts late.

Ignoring the main thread

A completed resource can still wait for browser work before paint.

Running Lighthouse once

One synthetic run is a diagnostic sample, not definitive evidence.

Mixing field and lab conclusions

Use each dataset for the question it can answer.

Delaying all JavaScript

Blanket changes can break dependencies or move the bottleneck.

Removing CSS without evidence

Only target CSS that contributes to the measured rendering path.

Testing only the homepage

LCP candidates and dependencies can differ by template.

Not re-checking the LCP candidate

An optimization may change which element becomes LCP.

What Not to Fix Yet

Before changing production, do not assume:

Image size is the problem
A CDN is required
Preload is required
CSS must be inlined
JavaScript must be delayed
Hosting must be upgraded

Diagnosis first. Optimization second.

Fix the Responsible Layer, Not the Metric

Root-cause category Fix direction
High TTFB Investigate server, cache, application, database or upstream response path
Late resource discovery Expose the critical resource earlier in the loading path
Slow resource transfer Improve resource delivery, selection, transfer size or network path
Element render delay Investigate main-thread work, CSS, JavaScript, DOM visibility and rendering dependencies

This matrix defines investigation direction. It is not an implementation checklist.

How to Verify an LCP Fix

A change is not complete until the intended bottleneck has been verified.

After remediation:

  • repeat the test under comparable conditions;
  • compare document timing;
  • compare LCP request start and finish times;
  • compare LCP paint timing;
  • confirm the LCP candidate;
  • inspect field trends when available;
  • check for layout, functionality, tracking or rendering regressions.

If a change improves image transfer but total LCP stays the same, investigate where the saved time moved.

See verify the optimization for the dedicated workflow.

When a Deeper LCP Investigation Is Needed

A deeper investigation is useful when:

Field LCP is poor but lab LCP is good
The LCP candidate changes between runs
The resource starts late for unclear reasons
The resource loads quickly but paint is delayed
Client-side rendering controls LCP visibility
Third-party code may compete for main-thread or network resources
TTFB and frontend delays both contribute
Previous fixes changed subparts without improving total LCP

A poor LCP score tells you that important content appeared too late, but it does not tell you which layer caused the delay. When the timing spans server response, resource discovery, network delivery and browser rendering, a root-cause investigation can isolate the responsible stage before production changes are made.

Know LCP is slow, but not which stage is responsible?

A structured Core Web Vitals investigation can separate server response, resource discovery, transfer and render delay so the responsible layer is identified before production changes are made.

WebPerfLab — Measure → Trace → Diagnose → Fix → Verify

Final Takeaway

LCP optimization starts with timing decomposition.

Ask:

  • Did the document arrive late?
  • Was the LCP resource discovered late?
  • Did the resource load slowly?
  • Did rendering happen late?

Then fix the responsible layer.

Measure→
Decompose→
Trace→
Confirm→
Fix→
Verify

Poor LCP is a symptom. Root-cause diagnosis determines the fix.