Skip to content

SpeedPart of: Image optimisation

The best image size for a website: pixels and file weight for every slot

The best image size for a website is the width the image is displayed at, times two for sharp screens: about 1600-2000 px for a full-width hero, 1200-1600 px for content images and 2× the slot for thumbnails, at under 100-300 KB each.

getReport teamUpdated 27 Sept 202612 min read

The best image size for a website is the width the image is actually displayed at, times two so it stays sharp on high-density (retina) screens: roughly 1600-2000 pixels wide for a full-width hero, 1200-1600 pixels for an image in a content column, and twice the slot for thumbnails. In file weight, aim for under 100 KB for most images and under 300 KB for the largest one on the page. Anything bigger downloads pixels the screen throws away. The pillar guide, image optimization for the web, covers format, compression and loading around these numbers.

This guide gives the recommended sizes for each common image slot, shows how to find the images on your pages that are too big in pixels or in kilobytes, and how to fix each one on any CMS.

Quick answer

  • Export at the displayed width × 2. A 400-pixel thumbnail needs an 800-pixel file at most.
  • Weights: under 100 KB for content photos, under 30 KB for thumbnails, under 300 KB for a full-width hero.
  • Format: WebP or AVIF at about quality 80 for photos, SVG for logos and icons.
  • Add width and height to every <img> so the browser reserves space; CSS can still scale it.
  • Offer several sizes with srcset so phones do not download the desktop file.
  • Run the image size checker to see pixels, displayed size and file weight for every image on a page.

These are starting points for a typical layout with a content column of 700-800 pixels and a maximum page width of about 1400 pixels. Measure your own slots (step 2) and adjust.

ImageDisplayed width (desktop)Export widthTarget weight
Full-width hero or banner1200-1440 px1600-2000 px (plus 800 and 1200 px versions in srcset)under 200-300 KB
Image in a blog post or content column700-800 px1200-1600 pxunder 100-150 KB
Product photo on a product page500-700 px1000-1400 px (a larger file for zoom, loaded on demand)under 150 KB
Card or grid thumbnail250-400 px500-800 pxunder 30-50 KB
Logo and iconsanySVGa few KB
Social share image (Open Graph)n/a1200 × 630 px, JPEG or PNGunder 300 KB

Why "times two": most phones and many laptops have screens with two or three device pixels per CSS pixel, so a 400-pixel slot shows 800 device pixels. Going to 3× rarely looks different and costs more than twice the bytes, which is why 2× is the usual ceiling. With srcset, each device picks the smallest file that covers its slot at its density.

A hero image size for a website deserves its own note. The hero is usually the page's Largest Contentful Paint element, so its weight decides your LCP. 2000 pixels covers a 1440-pixel desktop slot sharply enough for a photo; exporting 2880 or 3840 pixels for large retina desktops roughly doubles or quadruples the bytes for a difference few visitors see. Keep it under 300 KB as WebP or AVIF, never lazy-load it, and give it fetchpriority="high".

Why image size matters

Bytes cost time. On a phone with a 5 Mbit/s connection, a 1.8 MB hero takes about three seconds on its own, and Google's LCP threshold for "good" is 2.5 s. A 1600-pixel photo shown in a 300-pixel slot downloads 28 times more pixels than the slot can show; the browser decodes them and throws them away, which costs CPU as well.

Missing dimensions cause the second problem. When an <img> has no width and height, the browser does not know how tall it will be until the file arrives, so it lays out the text, then pushes it down when the image loads. That jump is what Cumulative Layout Shift measures, and images without dimensions are its most common cause.

How getReport checks it

The report reads every <img> on the page (including data-src and the first srcset candidate that lazy-load plugins use), requests the first 64 KB of each file to read its format and real pixel dimensions, and takes the file size from the Content-Length header, so nothing large is downloaded twice. With the width, height, loading and srcset attributes from the HTML, that gives four findings:

The heavy-files finding flags any image over 300 KB; the oversized finding flags images whose real width is more than twice the width in their width attribute. The table lists each image sorted by size with format, real pixels, displayed size, loading attribute and status:

Images table: a 1.8 MB PNG hero at 1200×520 displayed at 300×130 in red, three 800×800 thumbnails displayed at 120×120, a 1600×900 photo with no dimensions, and one image answering 404
Every image with its file size, format, real pixels, displayed size and loading attribute. Oversized and heavy files are highlighted.

The full report adds the total image weight including CSS backgrounds, and Lighthouse's sizing estimate. Lighthouse used to call that audit "Properly size images"; in Lighthouse 13 it is part of the "Improve image delivery" insight. It compares each image with the size it is rendered at in its test viewport and counts the bytes you would save.

How to fix oversized images, step by step

1. Sort by weight and fix the top three

The table is sorted by file size, and the top three rows are usually most of the image bytes. Fix those first; a long tail of 20 KB icons does not matter.

2. Compare real pixels with the displayed size

A row that says 1600×900 pixels, displayed at 300×169, is serving more than five times the width. Export at 600 pixels (twice the display width) and the file drops by around 85 %. If the displayed column says "not set", the page has no width and height attributes: right-click the image, choose Inspect, and hover the element in the browser's developer tools to read the rendered size.

3. Resize and compress

Resize to the export width from the table above, then save as WebP or AVIF at around quality 80. How to reduce image file size has the tools and settings, and AVIF vs WebP helps you pick the format. Screenshots with text stay lossless WebP or PNG; logos become SVG; a GIF animation of a few seconds becomes a muted, looping <video>, often a fraction of the size.

4. Add width and height

The attributes give the image's proportions; CSS still decides the display size. The browser uses the ratio to reserve space before the file arrives.

HTML
<!-- The ratio 3:2 comes from the attributes, CSS sets the display size -->
<img src="/img/runner-x-800.webp" alt="Blue running shoe, side view"
     width="800" height="533" loading="lazy" decoding="async">
CSS
img { max-width: 100%; height: auto; }

5. Serve several sizes with srcset

One file for every screen means phones download the desktop size. srcset lists the candidates and sizes tells the browser how wide the slot is at each breakpoint:

HTML
<img src="/img/runner-x-800.webp"
     srcset="/img/runner-x-400.webp 400w,
             /img/runner-x-800.webp 800w,
             /img/runner-x-1200.webp 1200w"
     sizes="(max-width: 640px) 100vw, 400px"
     width="800" height="533" alt="Blue running shoe, side view" loading="lazy">

Most CMSs generate the sizes on upload; the theme has to print the attributes. Responsive images with srcset and sizes explains how to write sizes for your layout.

6. Lazy-load below the fold only, and fix broken images

loading="lazy" on everything below the first screen, never on the hero; see how to lazy load images. A 404 in the table means the file moved or was deleted: re-upload it, fix the path (after a migration, check the uploads folder and CDN rewrite rules) or remove the tag.

Platform notes

  • WordPress resizes uploads into the sizes the theme registers; pick the size that matches the slot (the Resolution setting in the image block) rather than "Full Size". Since WordPress 5.3, uploads over 2560 pixels are scaled down to 2560 automatically. Images inserted through the editor get width, height, srcset and loading automatically; theme images and page-builder widgets often do not.
  • Shopify: the image_url and image_tag filters print srcset, width and height in Liquid:
Liquid
{{ product.featured_image | image_url: width: 800 | image_tag: widths: '400, 800, 1200', sizes: '(max-width: 640px) 100vw, 400px', loading: 'lazy' }}
  • Frameworks: Next.js, Astro and Hugo resize and convert at build time; the sizes attribute is still yours to write.
  • Image CDNs resize on request from one original, with the width in the URL. See image CDNs and on-the-fly resizing.

How to verify

  • The table shows no file over 300 KB, no "not set" in the displayed column and no 404.
  • The heavy, oversized and missing-dimensions findings pass, and the sizing finding shows near-zero savings.
  • LCP in the speed module drops; with the hero as the LCP element it should load within 2.5 s on mobile.

Common mistakes

  • Uploading camera originals. A 4000×3000 file scaled down with CSS. Export at the display size × 2.
  • Exporting everything at 3× or 4×. Bytes grow with the square of the width; 2× is the sensible ceiling.
  • height: auto without attributes. CSS alone does not reserve space; the ratio has to come from the attributes or aspect-ratio.
  • Lazy-loading the hero. It adds hundreds of milliseconds to LCP for no gain.
  • Serving the 2× file to every screen. srcset exists so a phone gets a phone-sized file.

Questions people ask

How wide should images be on a website?

Twice the width they are displayed at. Measure the slot in your layout: a content column of 800 pixels needs a 1600-pixel image, a 300-pixel card thumbnail a 600-pixel one, and a full-width hero about 1600-2000 pixels. Wider files look no sharper on screen and only add download time. Offer smaller versions with srcset so phones get a file that matches their screen.

How many kilobytes should an image be on a website?

Aim for under 100 KB for most content images and under about 200-300 KB for a full-width hero; the image size checker flags any single file over 300 KB. File size depends more on format and compression than on pixels: a 1600-pixel-wide photo usually fits in 150-250 KB as WebP at quality 75-80. Thumbnails should weigh a few tens of kilobytes at most.

What size should a hero image be?

Export a full-width hero at about 1600-2000 pixels wide, in WebP or AVIF, and keep the file under 300 KB; with srcset, offer smaller versions such as 800 and 1200 pixels for phones and tablets. The hero is usually the page's Largest Contentful Paint element, so do not lazy-load it, give it width and height, and add fetchpriority="high" so it starts downloading early.

What size should images in a blog post be?

Export them at twice the width of your content column: for a typical 700-800-pixel column that is 1400-1600 pixels wide, saved as WebP or AVIF at around quality 80 and ideally under 100-150 KB each. Let your CMS generate smaller versions for srcset, give each image width and height, and lazy-load everything below the first screen, since long posts often carry a dozen images.

Does image size affect page speed and SEO?

Yes. Heavy images are the most common reason a page's Largest Contentful Paint misses Google's 2.5 s threshold, and LCP is one of the Core Web Vitals Google uses as a ranking signal. Images without width and height also cause layout shift. Beyond rankings, a 2 MB hero takes seconds on mobile data and visitors leave. Smaller, correctly sized images improve both LCP and CLS.

Check your site before and after Check