Images are usually the bottleneck on Core Web Vitals scores. Three vitals (LCP, INP, CLS) are all touched by image decisions. Here's exactly what to do to hit Google's "Good" thresholds.
Core Web Vitals are Google's set of metrics that quantify "real user experience" — specifically loading speed, responsiveness, and visual stability. They directly influence search rankings and conversion rates. They're also the area where most websites have the most room to improve.
For most sites, images are the largest factor in two of the three Vitals. This article covers the specific techniques to address each Vital, with targets you should aim for.
Images affect LCP directly, CLS strongly, and INP indirectly. Let's go through each.
On most modern websites, the LCP element is a hero image — a large image at the top of the page. The time until that image renders determines your LCP score, and it's almost entirely about image optimization.
srcset to serve smaller images to phones.fetchpriority="high" to the hero image's <img> tag. This tells the browser to prioritize this image's download over others.<link rel="preload" as="image"> for the hero image. The browser can start downloading it before parsing the rest of the HTML.loading="lazy" on the hero image hurts LCP.<link rel="preload" as="image" href="/hero-1600.webp">
...
<picture>
<source srcset="/hero-800.webp 800w, /hero-1200.webp 1200w, /hero-2000.webp 2000w"
sizes="100vw"
type="image/webp">
<img src="/hero-1200.jpg"
alt="Description of the hero"
width="2000" height="1000"
fetchpriority="high">
</picture>
The width and height attributes prevent layout shift (more on CLS below). The fetchpriority="high" tells the browser to prioritize this image. The preload in the head starts download even earlier.
Cumulative Layout Shift happens when elements move around as the page loads. The biggest culprit: images without dimensions. The browser doesn't know how tall an image is until it downloads it, so the layout reflows when the image arrives.
Every image needs width and height attributes set on the <img> tag. The browser uses these to reserve space before the image loads.
<img src="photo.jpg" alt="..." width="1200" height="800">
The numbers don't have to match the displayed size. They define the aspect ratio. With width and height set, the browser reserves a 1200:800 box and fills it with the loaded image when ready, with no jumping.
When using CSS like img { width: 100%; height: auto; }, the width/height attributes still matter — modern browsers use them to compute aspect ratio. Set them, even if CSS overrides the actual rendered size.
font-display: optional or preload fonts).But for most sites, sizing images correctly fixes 80% of the CLS issue.
Interaction to Next Paint measures how quickly the page responds to user input. Image decoding is part of this — if a user taps a button while a large image is decoding on the main thread, the response is delayed.
Browsers normally decode images synchronously on the main thread. You can hint that an image can be decoded asynchronously:
<img src="photo.jpg" alt="..." decoding="async">
This tells the browser to decode the image off the main thread when possible. Combine with loading="lazy" for below-the-fold images.
An image at 5000×4000 has 20 million pixels to decode. Even if the file is only 800 KB (because it's heavily compressed), decoding it takes meaningful CPU time. Limit source dimensions to what you actually display.
The loading="lazy" attribute defers image download until the image is near the viewport. This helps overall page weight and INP.
Critical rule: only use lazy on below-the-fold images. The first 1-3 images that appear on the screen should load eagerly (default behavior). Lazy-loading them hurts LCP.
<!-- Hero image — load eagerly -->
<img src="hero.webp" alt="..." width="1600" height="900" fetchpriority="high">
<!-- Article image partway down — lazy load -->
<img src="diagram.webp" alt="..." width="800" height="500" loading="lazy">
For sites with many images, an image CDN (Cloudinary, imgix, Cloudflare Images, etc.) handles a lot of this automatically. They serve the right format and size based on the requesting device, with on-the-fly transformations.
For smaller sites, you can achieve the same result with pre-generated variants and srcset. The work is more upfront but the runtime cost is zero.
Don't optimize blind. Use these tools to measure:
<img> has width and height.fetchpriority="high".loading="lazy".srcset with multiple sizes.Hit all eight and your image-related Web Vitals will be in the top 10% of websites.
Prepare your hero images with pictoolkit's resize, compress, and WebP converter. All processing in your browser.