Published May 2026 · Updated May 27, 2026
According to HTTP Archive data, images account for roughly half of the average web page's total byte weight. For pages with large hero images or photo galleries, that proportion can climb to 70–80%. Downloading a 1.5MB JPEG over a mobile connection takes considerably longer than downloading a 200KB WebP at comparable quality — and that delay shows up directly in your performance scores.
Images affect performance in two distinct ways. First, they add to total page weight, which increases the time before the page is usable on slow connections. Second, they affect specific performance signals that Google and browsers measure — particularly how quickly the page's main content appears (LCP) and whether the layout shifts during loading (CLS).
The good news is that image optimization has a very high return on effort. Fixing image issues — resizing to appropriate dimensions, converting to WebP, adding loading="lazy" — typically moves performance scores more than any other single category of change.
Core Web Vitals are a set of metrics Google uses to measure user experience. They feed into Google's page experience ranking signals. There are three main metrics:
The most common image performance problem is serving images that are much larger than they are displayed. A camera photo at 4000×3000 pixels displayed in a 800×600 slot is wasting bandwidth — the browser downloads a 3MB file and shrinks it to 800px wide using CSS. The user sees no difference, but they waited for 2.5MB of extra data to download.
To check: open browser DevTools, inspect an image, and compare the natural (intrinsic) size to the displayed size. If a 1920px image is displayed at 400px, you are downloading roughly 23× more data than needed.
Different devices have different screen widths and pixel densities. The srcset attribute lets you provide multiple image files and let the browser pick the appropriate one:
<img
src="/images/hero-800.webp"
srcset="/images/hero-400.webp 400w,
/images/hero-800.webp 800w,
/images/hero-1200.webp 1200w"
sizes="(max-width: 600px) 100vw, 800px"
alt="Description of the hero image"
width="800"
height="500"
>
The sizes attribute tells the browser how wide the image will be displayed at different viewport sizes, so it can select the most appropriate source from srcset before making the network request.
Once you have the right dimensions, the format and compression level determine the actual file size. The modern web stack recommendation is:
For most hero images, the target file size should be under 150KB. For inline content images, under 100KB. For thumbnails, under 50KB. These are guidelines, not hard limits — a full-screen background image can be larger if it is loaded correctly (see preloading below).
By default, browsers begin loading all <img> elements in the page as soon as they parse the HTML, even images that are far below the visible area. For a long page with 20 images, this means loading content the user may never scroll to.
The loading="lazy" attribute tells the browser to defer loading images until they are near the viewport:
<img src="thumbnail.webp" alt="Product thumbnail" loading="lazy" width="200" height="200">
This is one of the highest-return, lowest-effort performance improvements you can make. Add it to all images except the one most likely to be the LCP element (typically the hero or first above-the-fold image). Lazy loading the LCP image would delay it and hurt your LCP score.
When a browser encounters an <img> element without explicit width and height attributes, it does not know how much space to reserve for it. The image loads, appears, and pushes surrounding content down — this is layout shift, and it is what the CLS metric measures.
Adding width and height attributes that match the image's aspect ratio allows the browser to reserve the correct space before the image downloads:
<img src="photo.webp" alt="Description" width="800" height="450">
You do not need to use these as fixed pixel dimensions in the layout — CSS can override the visual size. The important thing is that the ratio is correct so the browser can reserve proportional space. An 800×450 image and a 400×225 image have the same 16:9 ratio; either set of attributes will prevent CLS.
For your most important image — typically the hero or banner at the top of the page — you can ask the browser to start downloading it immediately, even before it processes the full HTML. Use a <link rel="preload"> tag in the <head>:
<link
rel="preload"
as="image"
href="/images/hero-800.webp"
imagesrcset="/images/hero-400.webp 400w, /images/hero-800.webp 800w"
imagesizes="(max-width: 600px) 100vw, 800px"
>
Preloading the LCP image is particularly effective when the image is referenced in CSS (as a background-image), which the browser cannot discover until after it has downloaded and parsed the stylesheet. If the image is in an <img> tag near the top of the HTML, preloading is less critical but still helpful.
The <picture> element allows you to provide different image formats and let the browser pick the best one it supports:
<picture>
<source type="image/avif" srcset="hero.avif">
<source type="image/webp" srcset="hero.webp">
<img src="hero.jpg" alt="Hero image description" width="800" height="450">
</picture>
Browsers that support AVIF will use the AVIF file. Browsers that support WebP (but not AVIF) will use the WebP file. All others fall back to JPEG. This approach gives you the best compression where it is supported without breaking compatibility.
Large images can take time for the browser to decode (decompress and render). The decoding="async" attribute tells the browser it does not need to finish decoding the image before rendering the rest of the page:
<img src="large-photo.webp" alt="Description" loading="lazy" decoding="async" width="1200" height="800">
For below-the-fold images, this prevents image decoding from blocking the main thread. For the LCP image, omit this attribute (or use decoding="sync") since you want it decoded as quickly as possible.
Work through this checklist to audit the images on any web page:
loading="lazy" to all <img> elements except the LCP image (usually the first hero or banner image).width and height attributes to every <img> element, matching the image's natural aspect ratio. This prevents Cumulative Layout Shift.<link rel="preload" as="image"> tag in <head> for the LCP image. This is especially important if the image is set via CSS background-image.