Technical walkthrough
What to know
Diagnose portfolio website LCP by identifying the actual LCP element and separating server time, resource discovery delay, download duration and render delay. Test representative pages under repeatable conditions, prioritise the first visible image, and report laboratory and field evidence separately.
Portfolio websites often make a visual promise before they make a technical one. The opening screen may be an oversized project photograph, an immersive render, a reel of recent work or a full-bleed image with a carefully chosen typeface. That first impression matters, but a large hero can become a liability if it appears only after a long chain of stylesheets, scripts and network requests.
Largest Contentful Paint (LCP) measures the time from navigation until the largest eligible image or text block in the viewport is rendered. Google's “good” threshold is 2.5 seconds or less at the 75th percentile of page loads. The number is useful, but the important question for a developer is where the delay happened.
This is a diagnostic walkthrough rather than a performance claim about any named Web Dev Awards entry. The timings and page examples below are illustrative; the method is reproducible on a site the developer is authorised to test.
Identify the actual LCP element first
A common mistake is to assume that the largest hero image is automatically the LCP element. On some viewports, the largest eligible element is a text block. On others, a slideshow image, poster frame or even a different gallery item may be the observed LCP candidate.
Start with the browser's Performance panel and a Lighthouse navigation trace. Capture a cold-load run on a consistent mobile viewport. Identify the LCP marker and inspect the element it names. Repeat on several pages rather than drawing conclusions from one homepage run.
Write down the URL, viewport, connection and CPU conditions, test time and whether any caching was warmed. Do not compare a cold network profile from one run with a warmed desktop profile from another and present the difference as proof of a fix.
If real-user data is available, compare it with your lab findings. Public CrUX data may be missing for low-traffic individual URLs. In that case, state the limitation; do not treat a Lighthouse result as the 75th-percentile user experience.
Decompose the delay instead of guessing
Google's LCP optimisation guidance breaks down image LCP into four useful components:
| Component | What it measures | What a developer should investigate |
|---|---|---|
| Time to first byte (TTFB) | Time before the HTML response begins | Hosting, redirects, middleware, cache misses, server work |
| Resource load delay | Gap after the HTML response before the LCP resource starts downloading | Resource discoverability, JavaScript injection, CSS backgrounds, lazy loading |
| Resource load duration | Time spent receiving the image | Transfer size, format, responsive selection, network contention, image origin |
| Element render delay | Time between the resource loading and the element actually rendering | CSS, long scripting tasks, animation gates, hidden or delayed content |
A 3.8-second illustrative LCP could involve a moderately slow server response, a very late image request, a short image download and an unnecessary animation gate. Compressing the file further would barely move the result. The primary fix is to make the right resource discoverable earlier and remove artificial display delay.
The trace should determine the work, not the latest optimisation fashion.
Check whether the HTML reveals the image early
Consider a portfolio page where the hero is created entirely after a client-side application hydrates:
function ProjectHero({ project }) {
return <HeroSlider slides={project.images} />;
}
This fragment isn't inherently wrong. The problem appears when the initial HTML contains no eligible image URL and the browser must first download JavaScript, execute the app, load project data and finally construct the hero. The network waterfall shows an avoidable gap between HTML arriving and the image request starting.
Where the architecture allows it, render the first visible image in initial HTML, with real src and srcset attributes. Keep carousel controls and enhanced animations as progressive enhancements rather than prerequisites for seeing the primary work.
A straightforward image might look like this:
<img
src="/images/project-hero-1200.webp"
srcset="
/images/project-hero-640.webp 640w,
/images/project-hero-1200.webp 1200w,
/images/project-hero-1800.webp 1800w
"
sizes="(max-width: 768px) 100vw, 70vw"
width="1800"
height="1200"
fetchpriority="high"
alt="Contemporary building facade photographed at dusk"
>
These filenames, dimensions and alt text are illustrative. Use real files, an accurate subject description and responsive breakpoints from the actual layout. The intrinsic dimensions preserve the aspect ratio; the sizes expression should reflect the rendered slot, not a guessed value. fetchpriority="high" can be appropriate for the identified primary LCP image; applying it to every thumbnail defeats its purpose.
Don't lazy-load the image that must appear first
Lazy loading is valuable for a grid of twenty project thumbnails below the fold. It is generally the wrong default for a hero that occupies most of the opening viewport.
If the main image has loading="lazy", the browser may wait for layout to decide whether the image is close enough to view. That additional discovery delay is exactly what the page needs to avoid. Use eager/default loading for the actual initial hero, and reserve lazy loading for offscreen images that do not define the opening experience.
A multi-slide carousel also needs careful prioritisation. The first visible slide may deserve an early request, but later hidden slides should not compete for bandwidth simply because they appear at the top of the document markup.
For a CSS background hero, the browser may need to download and parse CSS before discovering the image. Sometimes an appropriate preload helps, but avoid preloading multiple responsive candidates or a different image from the one actually shown. A mismatched preload can cause a duplicate download or unnecessary competition.
Fix the right image size, not just the image format
A 2,400-pixel image delivered to a 390-pixel phone is often wasteful, even if it uses a modern codec. Responsive images let the browser choose an appropriate resource, taking the layout and device pixel ratio into account.
Inspect the transferred image dimensions and file size in the Network panel. Confirm what the browser actually selected from srcset, not what the developer expected it to select. Review the displayed width at multiple breakpoints.
AVIF and WebP can reduce transfer size for many images, but image quality, transparency, encoder settings and visual content affect the result. A high-quality JPEG may still be an appropriate fallback. Test a few representative images rather than applying a single quality setting to the entire archive.
When screenshots are historic or contain small interface text, excessively aggressive compression can destroy the very details visitors are trying to inspect. An awards gallery must balance image quality with delivery efficiency.
Inspect server response and edge behaviour
Not every slow hero is an image problem. On a dynamic archive, the server may need to read project data, resolve an award record and fetch media metadata before it can build the page. If this work blocks the initial HTML, TTFB rises and every later resource begins late.
Use request traces or server logs to look for repeated database queries, slow data joins, unnecessary network calls and cache misses. Where the hosting model allows it, cache public, stable content safely. Preserve correctness when recognition labels, corrections or permissions change.
Avoid serving a stale or fabricated project record just to improve a benchmark. A fast page with the wrong award status is not a successful result.
On pages with content served from an image CDN or different media hostname, connection setup can also contribute to transfer delay. Investigate whether connection reuse, sensible caching or a different resource location helps. Do not introduce domain sharding or unneeded preconnect hints without measurement.
Don't hide content behind animation
A visual reveal may look polished in a design demonstration but delay LCP if the main element is initially hidden or blurred. If a hero image finishes loading and waits for a long animation before it is painted, the problem is render delay, not network speed.
Try the page with reduced-motion preferences enabled. Check whether the critical content appears immediately and remains legible. Reserve decorative transitions for after meaningful content is available, and do not force a user to watch an entrance sequence before reading the page.
Animations can also create layout instability. Set reliable image dimensions and fixed/aspect-ratio containers so content does not jump as galleries load.
Use a repeatable measurement protocol
For a small optimisation study, define a protocol before changing code:
- Select representative templates: homepage, project detail, studio page and gallery or category listing.
- Capture baseline mobile traces under repeatable conditions. Keep separate cold and warm-cache results.
- Record the actual LCP candidate and its four timing components.
- Make one class of change at a time, such as eager-loading the hero or correcting
sizes. - Re-run several tests and note variability. Compare the same URL and conditions.
- Check that the visual quality, navigation, accessibility and other Core Web Vitals have not regressed.
- Once deployed, compare real-user performance over a meaningful period if your analytics or CrUX coverage supports it.
An example result table should distinguish observed data from illustrative timings:
| Finding | Evidence to record | Candidate fix |
|---|---|---|
| Late image request | Network waterfall gap after HTML | Render hero URL in initial HTML |
| Main image lazy-loaded | Initial hero has loading="lazy" | Eager-load identified LCP element |
| Oversized mobile download | Selected srcset candidate much wider than slot | Correct sizes and available widths |
| Render blocked by animation | Image loaded before it appears | Remove critical-path display delay |
| Slow HTML | High TTFB across pages | Trace server queries and caching |
Do not publish a made-up “before 4.1s, after 1.8s” chart to make the case sound real. If the measurements have not been performed, the article remains a walkthrough, not a results-based case study.
Special considerations for award archives
Awards websites often display hundreds or thousands of screenshot-heavy profiles. Their performance risks extend beyond the homepage:
- Listing pages may eagerly download every thumbnail, including entries far below the fold.
- A profile image may be served in a much larger size than the actual display.
- Missing historic screenshots may trigger an unstable image container or an error state.
- A project gallery may initialise several slides and large libraries before the first visible screenshot appears.
- Filter interactions may cause expensive client-side work, turning a load-performance investigation into an INP problem as well.
A good archive uses explicit dimensions, responsive image delivery, bounded pagination, properly prioritised visible assets and reliable fallbacks. But it also keeps the records accurate, preserves important historic material, and offers an accessible way to browse without requiring animation or complex scripts.
Conclusion
The key to improving LCP is to understand why the browser was late. Sometimes the answer is a large image. Just as often, the browser learns about that image too late, the server responds slowly or the page hides ready content behind an effect.
Measure the actual element, break down the timeline, change the bottleneck and check the outcome. The result is not merely a better benchmark; it is a portfolio where the work visitors came to see becomes available sooner, across more devices and conditions.
Frequently asked questions
Is the largest hero image always the LCP element?
No. The actual element depends on the rendered viewport and eligible content. Check a browser trace before prioritising assets.
Should I preload all gallery images?
No. Excessive preloading creates contention and may slow the resource that matters most. Prioritise the first visible image only when the trace supports it.
Is AVIF guaranteed to improve LCP?
No. A smaller transfer can help, but server time, discovery delays, render gates and different image characteristics may dominate the total.
Can I rely on one Lighthouse run?
No. Repeatable lab runs are useful for diagnosis, while field data shows a broader real-user distribution where available. Report them separately.
Can I improve LCP without sacrificing image quality?
Often, yes. Better responsive selection, correct priorities, earlier HTML discovery and removing unnecessary rendering delays can help before more aggressive compression is considered.
Sources and further reading: Optimise Largest Contentful Paint · LCP explained · Core Web Vitals · MDN responsive images and img · Fetch priority
