A late hero image needs a loading investigation before it needs another compression pass. Next.js LCP optimization starts by identifying what actually becomes Largest Contentful Paint, when the browser discovers it, and what prevents it appearing. A small image can still arrive late if JavaScript reveals its URL or an animation hides the finished image.
This guide focuses on image discovery, responsive candidate selection and loading hints in Next.js. For metadata, canonicals and route setup, use the Next.js App Router SEO guide. The examples below are illustrative implementation patterns, not measurements from a client site. Check your installed Next.js version before copying component props.
Key takeaways
- Identify the actual LCP element before changing the hero.
- Match image sizes to the layout and inspect the selected URL.
- Choose loading hints for your Next.js version and avoid competing preloads.
- Compare controlled browser runs, then watch real-user data separately.
- What should you measure before changing the hero?
- Which part of the loading sequence is slow?
- Is the image URL available in the initial response?
- How should sizes match your Next.js layout?
- Should you use eager loading, fetchPriority or preload?
- What if the image is downloaded but still appears late?
- How do you validate the fix and report it honestly?
What should you measure before changing the hero?
Start with one public production URL and one repeatable browser configuration. Record the viewport, device pixel ratio, network profile, cache state and build identifier. As of this October 2026 review, Google's web.dev article Optimize Largest Contentful Paint defines good LCP as 2.5 seconds or less at the 75th percentile of visits. A single local run cannot establish that field result.
Open the production page directly, rather than navigating to it inside an already loaded application. A client navigation and a fresh document load exercise different paths. Make a separate note if the complaint only occurs after navigating from another page. Otherwise you risk improving the wrong loading sequence and losing the ability to reproduce the original problem.
Use the browser Performance panel to record a reload. Select the LCP event and inspect its associated element. The largest visible item might be a heading on mobile and a photograph on desktop. A decorative image far down the document may never become LCP, even if the marketing team calls it the hero.
The Chrome documentation Analyze runtime performance explains the recording workflow. Save the trace with your build identifier and test conditions. Keep a screenshot of the visible page as well. That pairing helps explain a later result when a layout change causes the LCP element itself to change.
Download the LCP investigation worksheet to organize observations. Its blank result columns are intentional. Populate them from your own tests; do not turn example values from another site into a performance baseline. The Core Web Vitals guide explains how field and laboratory evidence differ.
Which part of the loading sequence is slow?
Separate document waiting, image discovery, image transfer and final rendering. This creates a useful investigation order even when several problems coexist. The four-part model in web.dev's Optimize Largest Contentful Paint distinguishes time to first byte, resource load delay, resource load duration and element render delay. These are diagnostic categories, not independent ranking scores.
| Observation | First question | Evidence to save |
|---|---|---|
| HTML arrives late | Is the route waiting on a backend? | Document timing and server logs |
| Image request starts late | When did its URL become discoverable? | HTML response and request initiator |
| Image transfer takes long | Which candidate and bytes were sent? | Selected URL and response size |
| Image finishes before paint | What is hiding or blocking it? | Main-thread trace and computed styles |
A delayed document suggests checking route data fetching and caching before image hints. A late image request suggests inspecting markup and lazy loading. A long transfer suggests inspecting the responsive candidate and network contention. A finished image that remains invisible suggests CSS, animation, rendering work or application state. These branches make each code change easier to justify.
Avoid changing compression, caching, fonts and component structure in one experiment. If the result improves, you won't know which intervention mattered. Choose the largest observed delay, state your hypothesis, change one relevant input and repeat the same measurement. Keep the failed experiments too; they prevent another developer repeating an attractive fix that did nothing.
For document delays, continue with the server response time investigation. For slow interactions after loading, use the React INP guide. Loading and interaction complaints can occur together, but measuring one does not explain the other.
Is the image URL available in the initial response?
Check the document response for the image markup before investigating hydration. An image created only after a client fetch has a different discovery path from an image already described in HTML. Inspect the response and request initiator together; the Elements panel alone shows the current document and can hide how the image originally appeared.
Look for the actual image URL, generated optimization URL and responsive candidates. If the hero appears only after an effect sets state, move the initial image decision into a rendering path that can supply it sooner. Keep interactive controls client-side when necessary, while making the initial visual content independent of a later browser-only request.
A CSS background deserves a separate check. Google's web.dev article Don't fight the browser preload scanner explains that the scanner reads markup rather than external stylesheets. Consider whether the image is meaningful content that belongs in an image element. If a background is required, verify its actual discovery chain before adding a preload.
Don't remove a CMS image transformation just because its URL looks complicated. First determine whether the source URL is already available during rendering, whether the optimization endpoint responds successfully, and whether the requested variant matches the layout. A broken remote allowlist or failed image request needs a correctness fix before priority tuning can help.
Keep the initial hero stable across server and browser output. Replacing it immediately after hydration can start a second request or change the LCP candidate. If personalization is necessary, record its timing and test the default experience separately. An early generic hero and a later personalized hero are two resource decisions that deserve explicit review.
How should sizes match your Next.js layout?
Write the image's expected display width into sizes, then verify the browser's selection. The sizes value describes a layout slot, not a command to download a particular file. MDN's HTMLImageElement: sizes property explains how that hint works with width-based srcset candidates and device pixel ratio.
In this illustrative layout, the hero occupies the viewport minus side padding on narrow screens. Its desktop container stops growing at 1,120 CSS pixels. The sizes expression mirrors that rule. Replace the dimensions and breakpoint with the values from your actual stylesheet rather than copying a generic full-width declaration into a narrow column.
import Image from 'next/image'
export function Hero() {
return (
<div style={{ maxWidth: 1152, width: '100%', boxSizing: 'border-box', margin: '0 auto', padding: '0 16px' }}>
<Image
data-hero
src="/images/hero.webp"
alt="Describe the meaningful content of your actual photograph"
width={1600}
height={900}
sizes="(max-width: 1152px) calc(100vw - 32px), 1120px"
loading="eager"
fetchPriority="high"
style={{ width: '100%', height: 'auto' }}
/>
</div>
)
}
The image path above is hypothetical; supply your own file. The source dimensions reserve the aspect ratio, while CSS controls the rendered width. The Next.js documentation Image Component covers those props, responsive sizes and fill positioning. A fill implementation also needs a positioned parent with a defined layout size.
Select the hero in Elements, then run this diagnostic snippet in the console. MDN's HTMLImageElement: currentSrc property defines currentSrc as the URL the browser selected. Compare that URL with the matching Network request instead of assuming the src attribute reveals the file actually transferred.
const image = document.querySelector('img[data-hero]');
if (!image) throw new Error('Select or mark the actual hero image first');
console.table({
selectedUrl: image.currentSrc,
renderedCssWidth: image.getBoundingClientRect().width,
devicePixelRatio: window.devicePixelRatio,
sizes: image.sizes,
loading: image.loading,
fetchPriority: image.fetchPriority
});
Repeat with a fresh page at each viewport. Resizing an already loaded page can retain a larger cached candidate and confuse the comparison. Record CSS width and pixel ratio together: a high-density display can reasonably request more image pixels than the CSS width alone suggests. Inspect transfer bytes and visual quality before deciding the candidate is wasteful.
Should you use eager loading, fetchPriority or preload?
Choose the mechanism that addresses the observed discovery or scheduling problem. The current Next.js Image Component documentation deprecates priority from Next.js 16, describes preload, and recommends eager loading or high fetch priority in most cases. It advises against combining preload with loading or fetchPriority props. Check the version-specific API in your project.
The previous example uses eager loading with high fetch priority and no preload. Eager loading avoids deferring the known initial hero through lazy loading. Fetch priority communicates relative importance. These hints don't remove backend waits, enlarge available bandwidth or guarantee a paint time. Inspect the waterfall after the change to see whether scheduling actually changed.
If a known hero is discovered too late and preloading is appropriate, test a separate implementation using preload. Remove the explicit loading and fetchPriority props for that version's documented configuration. Don't add both implementations to the same page. Preserve responsive sizes so the browser and preload can agree on the needed resource rather than fetching mismatched candidates.
For an older Next.js release, use its versioned documentation instead of blindly renaming priority. The framework's generated markup and behavior are what matter. Record the installed version in the worksheet and inspect the production output after upgrading. A source-code search for a prop cannot prove what a specific deployed build sends to visitors.
Don't mark every carousel slide or product thumbnail as urgent. Competing high-priority resources weaken the intended ordering. Test the initial visible slide, hidden alternatives and mobile layout separately. A hero that changes at a breakpoint needs particular care: preloading both desktop and mobile images may transfer a file the visitor will never see.
What if the image is downloaded but still appears late?
Investigate visibility and main-thread work when the request finishes before the image appears. Start by temporarily disabling entrance animations and checking whether the LCP element changes. This is a diagnostic experiment, not a permanent recommendation to remove all motion. Save the trace that links the delayed paint to the relevant task or styling rule.
Inspect opacity, display, visibility and any overlay controlled by hydration. A finished image can sit behind a loading screen while unrelated code runs. Ask whether the initial hero really needs that screen. If the site waits for an analytics script or optional widget before revealing core content, separate the reveal condition from that optional dependency.
Check render-blocking CSS and long JavaScript tasks next. A download-size improvement may be real without improving the final paint when rendering remains blocked. Treat this as evidence to move to the next bottleneck, not as a reason to repeatedly lower image quality. Keep enough visual detail for the photograph to serve its purpose.
Use the image SEO guide for naming, meaningful alt text and image discoverability. Those practices support usability and search understanding, but they do not substitute for the timing investigation. Likewise, keeping this website's cover images below 150 KB is a publishing budget, not a universal LCP pass condition.
How do you validate the fix and report it honestly?
Repeat the same production-load test several times before and after the change, using a documented cache policy. Report the range and a representative summary, alongside the selected image and LCP element. Preserve the individual runs. This provides a check against celebrating one unusually fast result while overlooking inconsistent loading or a changed test setup.
Use the worksheet for mobile, tablet and desktop observations. Keep cold and warm cache runs in separate groups. Test the expected connection profiles rather than inventing a single score that represents every visitor. Confirm the image still looks acceptable, reserves its space and works with JavaScript unavailable where your rendering strategy supports that experience.
Field data needs its own observation period and sufficient traffic. A local improvement is evidence about that controlled test, not a measured change in all visitors or organic rankings. Document the deployment date, watch relevant page groups and avoid attributing later traffic movement to LCP without supporting evidence. Content, competition and other changes still affect search performance.
Does a WebP below 150 KB guarantee good LCP?
No. The request can start late or the image can wait behind rendering work. The worksheet separates the discovery, transfer and display questions so a smaller file does not hide the remaining bottleneck. Choose a useful visual-quality budget and verify the actual delivered candidate rather than treating one file-size limit as a complete performance test.
Should every above-the-fold image load eagerly?
Make a deliberate choice based on the initial visible layout and competing resources. The hero may need early loading while a hidden carousel slide does not. Test the real viewport and request ordering. If several images can become LCP, investigate that design before preloading all of them and increasing contention during the critical loading period.
Can Lighthouse prove a ranking improvement?
No. A controlled browser run helps diagnose loading behavior. Search rankings require separate evidence and cannot be inferred from one score. For implementation support, a website optimization review can connect route rendering, image delivery and browser traces to a prioritized set of fixes with a repeatable retest plan.
Start with the LCP element, choose the observed delay, and make one measurable change. A trace, responsive-candidate record and documented test setup make the outcome useful to the next developer. That evidence is more actionable than a checklist of image props applied without checking what the browser did.
