Back to Performance
Performance
medium
mid

What image optimization techniques do you use on the frontend?

Serve modern formats (AVIF/WebP), correct sizes via srcset, lazy-load below-the-fold, eager + fetchpriority='high' for the LCP image, reserve dimensions to prevent CLS, and use a CDN with on-the-fly resizing.

6 min read·~12 min to think through

Images are usually the largest assets on a page and the LCP element on most marketing pages. The optimization checklist:

  1. Format. AVIF (best compression) → WebP fallback → JPEG/PNG legacy. Most CDNs negotiate via Accept header.
  2. Right size. Use srcset + sizes so phones download a 400px version, not the 2400px hero. Skipping this is the #1 source of mobile data waste.
  3. Reserve space. Always set width + height (or aspect-ratio CSS) to prevent CLS when the image loads.
  4. Lazy-load below-the-fold. loading="lazy". Don't lazy-load the LCP image — pair eager + fetchpriority="high" for it.
  5. Preconnect / preload the LCP image origin.
  6. Compression. mozjpeg (lossy), oxipng/zopfli (lossless). Strip metadata.
  7. Responsive sources. <picture> with multiple <source> for art direction (hero on mobile vs desktop).
  8. CDN with on-the-fly resizing. Cloudflare Images, Vercel Image Optimization, Cloudinary. Source asset stays single-canonical; CDN serves variants.
  9. Decoding hint. decoding="async" for non-critical images so decode doesn't block paint.
  10. Inline tiny placeholders. A blurred 20-byte LQIP keeps perceived perf high.

Frameworks usually wrap the boilerplate: Next.js <Image> does srcset, format negotiation, lazy loading, and preconnect for free. Use it.

Code

tsx
<img
  src="/hero.webp"
  width={1600}
  height={900}
  fetchpriority="high"
  loading="eager"
  decoding="async"
  alt="FrontendAce dashboard"
/>
LCP-friendly hero image
tsx
<img
  src="/img-1200.jpg"
  srcSet="/img-400.jpg 400w, /img-800.jpg 800w, /img-1600.jpg 1600w"
  sizes="(max-width: 600px) 100vw, 800px"
  width={1600}
  height={900}
  alt="..."
/>
Responsive sizes with srcset

Follow-up questions

  • How does Next/Image handle format negotiation?
  • What's the difference between `loading='lazy'` and IntersectionObserver lazy?
  • Why does art direction need <picture> + <source> instead of srcset alone?

Common mistakes

  • Lazy-loading the LCP image and adding 200ms+ to LCP.
  • Skipping width/height and causing CLS on every image load.
  • Serving the same image to mobile and 4K monitors.

Performance considerations

  • AVIF saves ~30% over WebP, ~50% over JPEG at the same quality — biggest single win.
  • Sprite/SVG-icon strategy beats many small images for icons.

Edge cases

  • Animated content: GIF is huge; convert to MP4/WebM with `<video autoplay muted playsinline>` for ~10× smaller files.
  • Very tall images cause layout shift after lazy load if you don't set aspect ratio.

Real-world examples

  • Next.js Image, Astro Image, and Cloudinary's auto-format pipeline are de-facto standards in production stacks.

Senior engineer discussion

Senior signal: discuss the asset pipeline (build-time vs CDN), priority hints, content-aware compression, and how images interact with Core Web Vitals across pages.

Related questions