ILImageLens

Image optimization — practical guide

Everything ImageLens evaluates, with the why behind each rule and side-by-side examples.

1. Serve at the real displayed size

If an image renders at 320×320 on screen but the file is 1080×1080, you are sending ~10× more pixels than needed. Mobile pays for it in battery, data and load time.

Why: The browser must download and decode the full file before resizing. More pixels = more memory and time. For retina screens, serve at most 2× the displayed size.
Use on the LPRecommended widthTarget weight
Icon / avatar64–128px≤ 20 KB
Small card320–480px≤ 60 KB
Large card600–800px≤ 120 KB
Hero mobile600–900px≤ 150 KB
Hero desktop1200–1600px≤ 250 KB

Want to test a specific image? Use the Optimize image tab.

2. Use WebP or AVIF instead of PNG/JPG

Modern formats compress much better with no visible quality loss.

  • AVIFbest compression today (~50% smaller than JPEG). Ideal for photos.
  • WebPgreat balance of size and support. Recommended default.
  • PNGonly for logos, icons and art with transparency.
  • JPEGphotos when WebP/AVIF aren't possible.
  • SVGvector, scales without loss. Ideal for icons and logos.
Why: Swapping a 400 KB hero JPEG for AVIF typically drops to 120–180 KB at visually identical quality. On mobile 4G that is the difference between a 2.8s and 1.4s LCP.

You can convert with the Optimize image tab on this site, or with tools like Squoosh and TinyPNG.

3. srcset and sizes — one image per screen

With srcset you provide multiple versions of the image; the browser picks the best one for the current screen (width + pixel density).

Why: Without srcset, the same heavy file goes to the iPhone SE and to the 4K monitor. You waste bandwidth on small screens.
Do this
<img
  src="/img/produto-640.webp"
  srcset="
    /img/produto-320.webp 320w,
    /img/produto-640.webp 640w,
    /img/produto-1080.webp 1080w"
  sizes="(max-width: 768px) 80vw, 320px"
  alt="..."
  width="640" height="640"
  loading="lazy" decoding="async"
/>

The browser picks the right version per viewport and DPR.

Avoid
<img
  src="/img/produto-1080.png"
  alt="..."
/>

Same big file for everyone. No dimensions → CLS.

4. Lazy load below the fold (never on the LCP)

Use loading="lazy" on images below the first viewport. Never on the hero or LCP image.

Why: With lazy, the browser delays the download until the image is near the viewport. On the hero/LCP that postpones the largest element render — exactly what the Core Web Vital measures.
Do this
<!-- Hero / LCP: prioridade alta -->
<img src="/hero.webp" alt="..."
  fetchpriority="high" decoding="async" />

<!-- Abaixo da dobra: lazy -->
<img src="/depoimento.webp" alt="..."
  loading="lazy" decoding="async" />
Avoid
<!-- Lazy no hero atrasa o LCP -->
<img src="/hero.webp" alt="..."
  loading="lazy" />

5. Prioritize the LCP image

LCP (Largest Contentful Paint) is the time to render the biggest visible element — almost always a hero image. It is one of Google's three Core Web Vitals.

Why: fetchpriority="high" and &lt;link rel="preload"&gt; tell the browser "start downloading this before anything else". Without them, it discovers the image only after parsing the entire HTML.
<!-- No <head> -->
<link rel="preload" as="image"
  href="/hero-1200.webp"
  imagesrcset="/hero-600.webp 600w, /hero-1200.webp 1200w"
  imagesizes="100vw" />

<!-- No <body> -->
<img src="/hero-1200.webp" alt="..."
  width="1200" height="800"
  fetchpriority="high" decoding="async" />

6. Always set width and height

Even if CSS resizes it, declare width and height with the original ratio. The browser reserves the space before the image loads.

Why: Without dimensions, the content below is pushed when the image arrives — that is CLS (Cumulative Layout Shift), another Core Web Vital. Worse, readers tap the wrong button when the layout jumps.

Click "Reload" and watch the layout jump in the right card.

With width/height (no CLS)
Good example image

Text below the image stays stable.

Without dimensions (CLS)
Bad example image

Text below the image is pushed when it loads.

Do this
<img src="/foto.webp" alt="..."
  width="640" height="360" />

Reserved space → zero layout shift.

Avoid
<img src="/foto.webp" alt="..." />

Content below jumps when the image arrives.

7. Beware of CSS background-image

The browser discovers background-image late in the pipeline — only after downloading and parsing the CSS. For critical images (hero, LCP), prefer &lt;img&gt;.

Why: &lt;img&gt; tags are detected by the browser's preload scanner as soon as HTML arrives. background-image waits for the CSSOM. Typical difference: 200–600ms on LCP.
Do this
<!-- Hero como <img> -->
<img src="/hero.webp" alt="..."
  fetchpriority="high" />

Detected immediately by the preload scanner.

Avoid
<!-- Hero como background -->
<div class="hero" style="background-image: url(/hero.webp)"></div>

Only loads after CSS — delays LCP.

8. Final checklist

  • Real size checked (at most 2× the displayed size)
  • Converted to WebP or AVIF
  • Responsive variants with srcset + sizes
  • loading="lazy" on below-the-fold images
  • fetchpriority="high" + preload on the hero
  • width and height always set
  • Descriptive alt (a11y and SEO)
  • PageSpeed Insights re-run and LCP < 2.5s