fioelJournal

Core Web Vitals for image-heavy portfolio sites

6 min read 1303 words 6 sections 3 sources

Photo-heavy portfolio sites pass Core Web Vitals when the top photo loads first and the rest wait. Google's limits, and the order we fix things in.

By fioel, Amsterdamcore web vitals, performance, lighthouse

Contents06 sections
  1. 01Which Core Web Vital actually breaks a portfolio site?
  2. 02Why does Lighthouse show 100 when Search Console says the page is slow?
  3. 03How do I fix LCP when the hero is a photo?
  4. 04What actually causes layout shift on a gallery page?
  5. 05Does INP matter on a site that is mostly pictures?
  6. 06What do I check, in order?

Image-heavy portfolio sites pass Core Web Vitals when the browser loads one photo first and makes everything else wait. Google wants the main image on screen within 2.5 seconds (LCP), a response to every tap within 200 milliseconds (INP), and a layout shift score under 0.1 (CLS). At least three out of four real visits must meet these limits. Many photos on one page are fine. Sites fail when they load all of them at once.

Which Core Web Vital actually breaks a portfolio site?

Almost always it is Largest Contentful Paint (LCP). On a studio homepage the largest thing on the first screen is the hero photo. So LCP measures how long that one file takes to be found, downloaded, decoded and shown.

Google publishes the three metrics and their limits on web.dev1. The page is worth reading properly, because two details change how you should test.

First, the scores come from real visitors' phones and computers. Chrome sends them to the Chrome User Experience Report, which collects them over a rolling 28 days.

Second, the number that counts is the 75th percentile, so your fast visitors do not pull the score up. A page can feel instant on a Mac on office fibre and still fail, because a quarter of real visits come from something like a three-year-old Android phone on a train.

Layout shift (CLS) is the second most common problem on gallery pages, and site owners almost always cause it themselves. Interaction to Next Paint (INP) rarely causes trouble on a portfolio, with two exceptions I cover below.

Why does Lighthouse show 100 when Search Console says the page is slow?

They measure different things. Lighthouse is a lab test: one run, on one simulated device, over a simulated network. Search Console shows data from real Chrome users over 28 days. A perfect lab score next to a failing real-user score is normal, and the gap between them tells you something useful.

Lighthouse's mobile test simulates a slow 4G connection and a processor four times slower than normal, on a single first visit. That gives you a repeatable diagnosis of why a page is slow. It cannot tell you whether your visitors have a slow experience. It does not know that half of them arrive through the Instagram in-app browser on a mid-range phone.

So we use both, for different jobs. Real-user data from the CrUX dataset2 tells us whether there is a problem. Lighthouse tells us what is causing it. PageSpeed Insights on mobile shows both side by side, and it is the one check anyone can run on their own site in a minute.

How do I fix LCP when the hero is a photo?

Make the browser find and download that one image before anything else. Then make the file small enough to arrive in about a second on a slow connection. These are two separate problems, and you have to solve both.

Never lazy-load the hero

The most common well-meant mistake we find is loading="lazy" on every image. On the hero it stops the browser finding the image until the page layout is done. On a phone that can add a second or more to LCP. Lazy-load every image below the first screen, and never the LCP image.

The same goes for heroes that JavaScript adds to the page. A slider or carousel that builds its first slide with a script hides the most important file on the page. The browser first has to download the script, read it and run it. If the first slide is plain HTML, the script no longer slows LCP down.

Tell the browser it matters

Google's fetch priority guidance3 documents two tools: fetchpriority="high" on the hero image, and a preload if the browser finds the image late. Each one costs a single attribute. When the first impression of a page is one photo, that attribute helps more than any build tooling.

Size the file to the container, not to the camera

A 4000 pixel wide export from a photographer's delivery folder is far too big for the web. Serve modern formats, and use srcset so a phone downloads a phone-sized file. I work to a rule-of-thumb budget: the hero under 200 KB, no single WebP over 180 KB, and the first screen under about 1 MB in total. I explain where the export comes from and what to ask a photographer for in my note on photography for interior design sites.

Preload one font weight, and only one

When a font loads late and swaps in, the layout shifts and the text appears later. Usually font-display: swap plus a preload of the one weight used on the first screen is enough. If you preload four weights, that is four files competing with the hero for bandwidth at the moment the hero needs all of it.

Three things cause it, from most to least common: images without set dimensions, fonts that swap in at a different size, and banners added after the page appears.

An image without width and height attributes, or a CSS aspect-ratio, takes up no height until it loads. Then it pushes everything below it down. In a masonry grid of thirty photos, the page visibly jumps around for several seconds. The fix is simple and it solves the problem completely: give every image its real ratio, so the browser saves the space before the pixels arrive.

Cookie banners and newsletter pop-ups that push content down are the other common cause. If a banner has to appear, give it a fixed position on top of the page instead of a slot in the flow.

The limit is 0.1, and a gallery can easily score zero. If yours shifts, open it on a phone and watch which images jump.

Does INP matter on a site that is mostly pictures?

Yes, at two moments: when someone opens the lightbox and when they use a filter. Interaction to Next Paint replaced First Input Delay as a Core Web Vital in March 2024. The old metric only measured the wait before the page started handling a tap. INP measures the whole time until the screen updates.

On portfolio sites, two patterns fail. One is a project filter that redraws a large grid on every click. The other is a lightbox that decodes a full-size image on the main thread while it animates. You fix both by decoding images off the main thread and keeping the number of elements in a gallery reasonable. Scroll animation libraries that attach unthrottled listeners are the other usual cause.

What do I check, in order?

We run these checks on every image-heavy site, and they fix most failures.

  1. Find the LCP element in Lighthouse. It is often not the one you expected.
  2. Check that the element is in the first HTML the server sends.
  3. Remove loading="lazy" from it and add fetchpriority="high".
  4. Check its download size on mobile. Re-export anything over 200 KB.
  5. Check that srcset sends a phone-sized file to a phone.
  6. Give every image a set aspect ratio.
  7. Preload one font weight and let the rest load normally.
  8. Check the real-user data again after 28 days, instead of trusting a lab test after five minutes.

Studios find that last step the hardest. Real-user data updates over a rolling month, so a fix you ship today appears in Search Console gradually over the next four weeks. The lab test shows you made the right change, and the real-user data shows it helped your visitors. The award-winning portfolio sites I look at still use plenty of photos. They are fast because only one photo is allowed to load first.

Sources

  1. 01web.devweb.devBack
  2. 02CrUX datasetdeveloper.chrome.comBack
  3. 03fetch priority guidanceweb.devBack

05 questions

Questions this piece answers

Q01What is a good LCP for a homepage that opens with a photo?

Google's limit is 2.5 seconds for at least three out of four real mobile visits (the 75th percentile). For a hero photo that usually means a file under about 200 KB in a modern format. It should be in the first HTML the browser receives and marked as high priority.

Q02Why does my Lighthouse score differ from Search Console?

Lighthouse runs one test on a simulated slow phone. Search Console shows data from real Chrome users over the last 28 days, at the 75th percentile. Lighthouse tells you why a page is slow, and the real-user data tells you whether it is slow.

Q03Should I lazy-load images on a portfolio site?

Yes, for every image below the first screen, but never for the hero. Lazy-loading the largest image delays the moment the browser finds it. On studio websites that is the most common reason LCP fails.

Q04How many photos can one page have?

As many as you like, as long as only the first screen loads straight away. My rule of thumb is to keep the first screen under about 1 MB and let the rest load as people scroll. Photos further down the page barely affect Core Web Vitals.

Q05How long before a fix shows up in Search Console?

About four weeks. Search Console collects real-user data over a rolling 28 days, so an improvement shows up gradually. Check the fix in Lighthouse on the day, then confirm it in Search Console a month later.

Next piece6 min read8 Sep 2026How to photograph and order a project for the webShow each interior project in the same order: one wide shot of the finished room, then the before or the plan, three to six rooms and two close-ups.