ScreenshotNeo

BlogHow-to

How to Optimize Images for Fast Website Loading

Reduce image bytes, serve the right dimensions, prioritize critical images, prevent layout shifts, and measure the result with a practical implementation guide.

By the ScreenshotNeo team1 October 20268 min read

Fast image loading comes from sending fewer bytes at the right dimensions, making critical images discoverable, deferring images users cannot see yet, and reserving space before images arrive. No single format or attribute fixes every page. Measure the rendered result, transfer size, and field performance before and after each change.

1. Inventory the images that matter first

Start with the largest and most prominent images, especially the image that becomes Largest Contentful Paint (LCP). For each image, record:

  • Rendered width and height at common mobile and desktop viewports.
  • Intrinsic pixel dimensions.
  • Transferred bytes and decoded memory size.
  • Format and compression settings.
  • Whether it is visible in the initial viewport.
  • Whether it is an LCP candidate, below the fold, decorative, or content that must remain accessible.

Browser developer tools can show the requested URL, response size, timing, and the file selected from a srcset. Check mobile and desktop separately. Serving a desktop-sized file to a phone can use two to four times more data than necessary, according to web.dev guidance.

2. Resize images to the largest real display size

Do not upload a 3000-pixel-wide source when the largest rendered slot is 1200 pixels. Keep a high-resolution master if you need it, but generate delivery variants close to the sizes your layout actually uses.

A practical starting set might be 320, 640, 960, 1280, and 1920 pixels wide. Remove candidates that are nearly identical in size, and verify which candidate browsers select. The right set depends on your breakpoints, content, and traffic mix.

3. Use responsive images with srcset and sizes

For width-based variants, use srcset with width descriptors and describe the rendered slot with sizes:

<img
  src="/images/product-960.jpg"
  srcset="
    /images/product-320.jpg 320w,
    /images/product-640.jpg 640w,
    /images/product-960.jpg 960w,
    /images/product-1280.jpg 1280w,
    /images/product-1920.jpg 1920w"
  sizes="(max-width: 640px) 100vw, (max-width: 1100px) 80vw, 960px"
  width="960"
  height="640"
  alt="Product displayed on a desk"
>

The browser combines the slot width, device pixel ratio, and network conditions to choose a candidate. The sizes value must describe your CSS layout; an incorrect value can cause an unnecessarily large download.

For art direction, where the crop or composition changes at a breakpoint, use <picture>:

<picture>
  <source media="(max-width: 700px)" srcset="/images/hero-mobile.avif" type="image/avif">
  <source media="(max-width: 700px)" srcset="/images/hero-mobile.webp" type="image/webp">
  <source srcset="/images/hero-wide.avif" type="image/avif">
  <source srcset="/images/hero-wide.webp" type="image/webp">
  <img src="/images/hero-wide.jpg" width="1600" height="900" alt="A runner on a trail">
</picture>

4. Select a format based on the image and audience

Format Good fit Trade-offs
SVG Logos, icons, and vector artwork Not a replacement for photographic raster images
WebP General photographic and graphic images; transparency Choose lossy or lossless settings per image and check compatibility needs
AVIF Images where it produces a smaller file at comparable visual quality Provide fallback or negotiated delivery where required by your audience
JPEG Compatibility and photographs when it is the best measured result May be larger than WebP or AVIF for the same visual result
PNG Images needing lossless output or specific transparency behavior Often unnecessarily large for photographs

WebP supports lossy and lossless compression and transparency. AVIF can be smaller than older formats, but savings vary by image content and encoder settings. Compare files at the same displayed dimensions and inspect the rendered result. Do not choose a format from a universal percentage claim.

If your server varies the format using the request’s Accept header, configure shared caches to distinguish variants with Vary: Accept. Otherwise a cache can serve the wrong representation to a later request.

5. Compress while protecting visible quality

  1. Resize the source to the delivery dimensions.
  2. Export a WebP or AVIF candidate and an appropriate fallback.
  3. Compare the rendered image at the size users see it, including fine details, text in images, faces, and gradients.
  4. Record the file bytes and keep the smallest version that still meets your visual requirement.

Tools such as Squoosh, ImageOptim, and image optimization services can help create variants. Automate this in your build or content pipeline so new uploads follow the same process.

6. Lazy-load only images below the fold

Add loading="lazy" to images users must scroll to see:

<img
  src="/images/gallery-640.webp"
  width="640"
  height="427"
  loading="lazy"
  decoding="async"
  alt="Gallery item"
>

Leave the hero and other initial-viewport images eager and discoverable. Applying lazy loading to every image can delay an image that is visible immediately, including the LCP element. Browser heuristics decide the exact loading distance, so confirm behavior in the network panel.

7. Reserve layout space to prevent CLS

Set accurate width and height attributes, or define an equivalent CSS aspect ratio:

.card-image {
  aspect-ratio: 4 / 3;
  overflow: hidden;
}

.card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

These dimensions reserve the box before the response arrives. They address layout stability and do not reduce transfer time by themselves. Make sure the ratio matches the actual asset or crop.

8. Make the critical image discoverable and prioritize carefully

Keep the important image in the initial HTML when possible. If it is genuinely the critical LCP resource, fetchpriority="high" can help the browser prioritize it:

<img
  src="/images/hero-1280.webp"
  srcset="/images/hero-640.webp 640w, /images/hero-1280.webp 1280w, /images/hero-1920.webp 1920w"
  sizes="100vw"
  width="1920"
  height="1080"
  fetchpriority="high"
  alt="Mountain landscape"
>

Use this on the truly critical image only. Raising one resource can delay another. Preload when normal discovery is delayed, such as an image referenced only from CSS or injected late by JavaScript:

<link rel="preload" as="image" href="/images/hero-1280.webp" type="image/webp">

Do not preload multiple competing formats or every image on the page. Preloads compete with scripts, fonts, and other important resources.

9. Put the implementation together

<picture>
  <source
    type="image/avif"
    srcset="/images/hero-640.avif 640w, /images/hero-1280.avif 1280w, /images/hero-1920.avif 1920w"
    sizes="100vw"
  >
  <source
    type="image/webp"
    srcset="/images/hero-640.webp 640w, /images/hero-1280.webp 1280w, /images/hero-1920.webp 1920w"
    sizes="100vw"
  >
  <img
    src="/images/hero-1280.jpg"
    srcset="/images/hero-640.jpg 640w, /images/hero-1280.jpg 1280w, /images/hero-1920.jpg 1920w"
    sizes="100vw"
    width="1920"
    height="1080"
    fetchpriority="high"
    alt="Mountain landscape at sunrise"
  >
</picture>

<img
  src="/images/article-640.webp"
  srcset="/images/article-320.webp 320w, /images/article-640.webp 640w, /images/article-960.webp 960w"
  sizes="(max-width: 700px) 100vw, 720px"
  width="960"
  height="640"
  loading="lazy"
  decoding="async"
  alt="A close-up of a camera lens"
>

10. Measure before and after

  • Record transferred bytes for the page and for the largest images.
  • Check the selected candidate at representative viewport widths and device pixel ratios.
  • Inspect request start time, response time, decode time, and whether the LCP image was discovered early.
  • Verify that below-the-fold images do not load until needed.
  • Check layout shifts while images arrive.
  • Use field data where available and segment mobile and desktop. Web.dev guidance commonly uses 75th-percentile targets of LCP 2.5 seconds or less, INP 200 milliseconds or less, and CLS 0.1 or less. These are page experience targets, not guarantees from image compression alone.

Image work can improve LCP and data usage, but scripts, fonts, server response time, connection quality, and layout also affect Core Web Vitals. Attribute a change only after comparing the relevant timings.

11. Troubleshooting common image-loading problems

Symptom Likely cause Fix
A phone downloads a huge image Missing or incorrect sizes, or no srcset Describe the rendered slot and provide width-based candidates
The hero appears late It is lazy-loaded, injected by JavaScript, or hidden behind CSS discovery Keep it in initial HTML, remove lazy loading, and consider one preload or fetchpriority="high"
The page jumps when images load Missing dimensions or an incorrect aspect ratio Set width/height or a matching aspect-ratio
AVIF is not shown Missing fallback or unsupported client path Use <picture> with WebP and JPEG fallback, or correct content negotiation
The cache serves the wrong format Format negotiation is not represented in the cache key Send Vary: Accept and configure the CDN accordingly
Lazy images load too early or too late Browser distance heuristics or incorrect markup Apply lazy loading only below the fold and verify actual requests on representative devices
Images look soft Candidate is too small, over-compressed, or stretched Generate a larger candidate, correct sizes, and compare quality at rendered size
Optimization increases page time Too many preloads or high-priority hints compete with other resources Keep one critical priority and remove unnecessary preloads

12. Performance, reliability, and cost considerations

Responsive variants reduce transfer and decode work, but each variant adds storage, cache entries, and build complexity. Keep the candidate set manageable. Compression quality is an image-by-image decision. A CDN or image service can automate resizing and format negotiation, but measure cache hit behavior and validate fallback delivery. Avoid generating a different URL for every tiny width unless your traffic and cache strategy justify it.

For reliable rendering, keep meaningful alt text, ensure the fallback URL works, and test slow connections, disabled JavaScript, and browsers that do not support your preferred format. If an image is decorative, use an empty alt attribute rather than forcing screen readers to announce it.

Or skip the browser setup

If you need screenshots of optimized pages, responsive variants, or visual checks in an automated workflow, ScreenshotNeo returns a screenshot or PDF from one GET request. It accepts the cookie or consent banner like a visitor, removes more than 60 known consent platforms plus newsletter popups and chat widgets before capture, and lets you turn each step off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed; the response identifies the result with X-Page-Verdict and X-Billed.

See the ScreenshotNeo API documentation for all options, including full-page capture, element selectors, device presets, retina scale, waits, custom CSS and JavaScript, blocked resources, headers, cookies, geolocation, caching, signed links, asynchronous jobs, bulk capture, and the usage API.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also provides an MCP server so Claude, Cursor, and other MCP clients can call take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

FAQ

Should every image use WebP or AVIF?

No. Choose the format that gives the required visual quality and compatibility at the smallest measured size. SVG remains appropriate for vector artwork, and JPEG or PNG can still be the correct fallback.

Is lazy loading always faster?

It reduces work for images below the fold. It can delay visible images, so keep the hero and other initial-viewport images eager.

Do width and height make an image download faster?

No. They reserve layout space and reduce layout shifts. Reduce bytes with resizing and compression.

When should I preload an image?

Use one when normal discovery is delayed. Avoid preloading multiple formats or many images because they compete with other resources.

How much faster will optimization make my site?

There is no fixed gain. The result depends on image bytes, dimensions, LCP selection, connection, browser, and the rest of the page. Measure both lab and field data.