The heaviest element on most web pages is almost always an image. A well-optimised site hits 1.5 s LCP (Largest Contentful Paint); a neglected one sits at 5 s+. This guide covers which format to use in 2026, how to deliver the right size with srcset, and the truth about lazy loading and priority hints.
Formats — JPEG, PNG, WebP, AVIF
| Format | Strength | Weakness | Support (2026) |
|---|---|---|---|
| JPEG | Universal, great photo compression | No transparency, 20–50% larger than WebP/AVIF | 100% |
| PNG | Lossless, transparency, simple graphics | Bloated for photos | 100% |
| WebP | 25–35% smaller than JPEG, transparency | Misses some legacy environments | 97%+ (Safari 14+) |
| AVIF | 50% smaller than JPEG, HDR | Slow encoding | 93%+ (Safari 16+) |
| SVG | Vector, scales infinitely | Not for raster photos | 100% |
2026 recommendations:
- Logos and icons: SVG.
- Photos (blog, hero): AVIF with WebP and JPEG fallbacks.
- UI illustrations, transparent graphics: WebP or PNG.
Quality vs file size
The quality slider in JPEG/WebP/AVIF is not a percentage — 80 means different things in each format. Good defaults:
- JPEG quality 80 — visually indistinguishable; you can drop to 50 on mobile and most users won't notice.
- WebP quality 75–80 — matches JPEG 80.
- AVIF quality 50–60 — matches JPEG 80, with much smaller files.
Different sites have different sweet spots. Image Resize & Compress has a quality slider and a compression-ratio readout to find your threshold quickly.
Resolution — match the device
The biggest waste: sending a 1920 px image to a 360 px mobile. Even with retina (2×), 720 px is enough; the rest is traffic you'll never see.
Provide candidates via srcset and let the browser pick:
<img
src="hero-1280.jpg"
srcset="hero-640.jpg 640w, hero-1280.jpg 1280w, hero-1920.jpg 1920w"
sizes="(max-width: 768px) 100vw, 50vw"
alt="..."
loading="lazy"
width="1280"
height="720"
/>srcset— candidates + width descriptor (w).sizes— how wide the image will render. The browser uses this to pick from srcset.widthandheightattributes — establish aspect ratio → no CLS. (CSS can still resize while preserving ratio.)
Multiple formats with picture
Prefer AVIF/WebP, fall back to JPEG.
<picture>
<source type="image/avif" srcset="hero.avif" />
<source type="image/webp" srcset="hero.webp" />
<img src="hero.jpg" alt="..." loading="lazy" />
</picture>The browser picks the first source it can handle. If none, the final img. srcset works inside source too.
Lazy loading
Images outside the viewport don't need to load up front.
<img src="..." loading="lazy" alt="..." />Chrome 76+, Firefox 75+, Safari 15.4+. For the LCP candidate (the big hero image), use eager + high priority:
<img
src="hero.jpg"
loading="eager"
fetchpriority="high"
alt="..."
/>fetchpriority was standardized in 2024. It tells the browser which image is the LCP candidate among several.
Inline base64 vs external file
Small icons (under ~1 KB) can be inlined as base64 data URIs to save an HTTP request. Caveats:
- Base64 is ~33% larger than raw — inlining big images backfires.
- Not cached. The same image on multiple pages is downloaded each time.
- Most common as
background-image: url(data:...)in CSS.
Drop an image into Image to Base64 (Data URI) for an instant data URI; decide based on the resulting size.
SVG optimization
- Editor exports (Illustrator, Figma) include extra noise. Run through
svgoor SVGOMG (browser) — 50–80% reductions are routine. - Keep
viewBox; remove fixedwidth/heightso CSS can resize freely. - XSS risk — sanitize user-provided SVG with DOMPurify before inlining. External
<img>is safe.
CDN + dynamic resize
Cloudflare Images, imgix, and Cloudinary expose URL parameters for on-the-fly resize, format conversion, and quality control — img.example.com/hero.jpg?w=640&fm=avif style.
- Pro: one source → device-specific optimization automatically.
- Con: costs money. Small sites do fine with build-time static resize.
Static-site frameworks (Next.js, Astro, Hugo) resize at build time; next/image auto-generates srcset and picture.
Common pitfalls
1. Serving the original
A 4000-px RAW dropped straight into <img>. CSS sizes it to 200 px but the user still downloads 4000 px. Resize at build or via CDN.
2. Missing width/height
Without the ratio, the browser shifts layout when the image loads → CLS penalty in Core Web Vitals. Set the attributes or use CSS aspect-ratio.
3. PNG for photos
PNG is for graphics and icons. Photos in PNG are 3× the size of an equivalent JPEG/WebP/AVIF for the same visual quality.
4. Lazy-loading everything
Marking the first-viewport image loading="lazy" delays LCP. Above-the-fold images need eager + high priority.
5. Using CSS background for content images
<img alt> beats CSS background for SEO and accessibility. Reserve background-image for decoration.
6. Empty or "image" alt
alt is read by screen readers, indexed by search engines, and shown when the image fails. Write meaningful text. For pure decoration, use alt="" explicitly.
Core Web Vitals impact
- LCP — the hero image is usually the LCP element. AVIF + priority + proper size keeps LCP under 2.5 s.
- CLS — prevent with width/height attributes.
- INP — image decoding can block the main thread.
decoding="async"moves it off-thread.
Summary
- Format priority: AVIF > WebP > JPEG for photos; SVG for logos and icons; PNG for transparent graphics.
<picture>+srcset+sizesdeliver the right image per device.- Always include
widthandheight— no CLS. - LCP candidate = eager + fetchpriority high. Everything else = lazy.
- Tiny icons inline as base64. Larger images stay external and cache.
- Quick quality tuning lives in Image Resize & Compress with a slider and compression readout.