DNA🚀 PerformanceImage, Video & Font Optimization
ðŸĢHatchlingPerformanceImagesFontsWeb Vitals

Image, Video & Font Optimization

Media assets dominate page weight. Optimizing images, video, and fonts is the highest-leverage performance work — often cutting LCP by 50% or more with straightforward techniques.

Image, Video & Font Optimization

On a typical web page, images account for 50-70% of total bytes. Add video and fonts, and media easily exceeds 80%. Optimizing these assets is the single highest-impact performance work you can do.

Image Optimization

Format Selection

FormatBest ForCompressionBrowser Support
AVIFPhotos, illustrationsBest (30-50% smaller than WebP)Chrome, Firefox, Safari 16+
WebPPhotos, illustrationsExcellent (25-35% smaller than JPEG)Universal
JPEGPhotos (fallback)GoodUniversal
PNGTransparency, screenshotsLosslessUniversal
SVGIcons, logos, illustrationsVector (scales perfectly)Universal

Responsive Image Strategy

<picture>
  <source
    srcset="hero-400.avif 400w, hero-800.avif 800w, hero-1200.avif 1200w"
    sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
    type="image/avif"
  />
  <source
    srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
    sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
    type="image/webp"
  />
  <img
    src="hero-800.jpg"
    srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
    sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
    alt="Mountain landscape"
    width="800"
    height="450"
    loading="lazy"
    decoding="async"
  />
</picture>

Loading Priorities

<!-- LCP image: load immediately with high priority -->
<img src="hero.avif" fetchpriority="high" loading="eager" alt="Hero" />
 
<!-- Below-fold images: lazy load -->
<img src="product.avif" loading="lazy" decoding="async" alt="Product" />

Preventing Layout Shift

Always set explicit dimensions or use CSS aspect-ratio:

img {
  max-width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
}

Image CDN Pipeline

Modern image CDNs (Cloudinary, imgix, Vercel Image Optimization) handle:

  • Format auto-negotiation via Accept header
  • Responsive resizing via URL parameters
  • Quality optimization (perceptual quality vs file size)
  • CDN caching at edge locations
<img
  src="https://cdn.example.com/hero.jpg?w=800&q=80&f=auto"
  alt="Hero image"
/>

Video Optimization

Encoding Best Practices

CodecContainerUse Case
AV1WebMBest compression, limited hardware encoding
VP9WebMGood compression, wide support
H.264MP4Universal fallback

Lazy Loading Video

<video
  preload="none"
  poster="thumbnail.jpg"
  width="720"
  height="405"
>
  <source src="video.webm" type="video/webm; codecs=vp9" />
  <source src="video.mp4" type="video/mp4" />
</video>

Background Video Pattern

Replace GIFs (which are massive) with muted autoplay video:

<video autoplay muted loop playsinline preload="metadata">
  <source src="animation.webm" type="video/webm" />
  <source src="animation.mp4" type="video/mp4" />
</video>

A 10-second WebM is typically 80-90% smaller than the equivalent GIF.

Video Facade Pattern

Don't embed YouTube/Vimeo iframes eagerly — they load 500KB+ of scripts:

function VideoFacade({ videoId }: { videoId: string }) {
  const [loaded, setLoaded] = useState(false);
 
  if (loaded) {
    return (
      <iframe
        src={`https://www.youtube.com/embed/${videoId}?autoplay=1`}
        allow="autoplay"
        title="Video player"
      />
    );
  }
 
  return (
    <button onClick={() => setLoaded(true)}>
      <img
        src={`https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`}
        alt="Play video"
        loading="lazy"
      />
    </button>
  );
}

Font Optimization

Font Loading Strategy

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-var.woff2') format('woff2');
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC;
}

font-display Values

ValueBehaviorBest For
swapShow fallback immediately, swap when loadedBody text
optionalBrief block, use if ready, skip if notNon-critical text
fallbackShort block (100ms), swap period (3s)Balance flash vs invisible
blockLong invisible periodIcon fonts (if you must)

Preloading Critical Fonts

<link
  rel="preload"
  href="/fonts/inter-var.woff2"
  as="font"
  type="font/woff2"
  crossorigin
/>

crossorigin is required even for same-origin fonts — the font loading spec mandates it.

Subset Fonts

If you only need Latin characters, subset the font to remove unused glyphs:

pyftsubset Inter.woff2 \
  --output-file=Inter-latin.woff2 \
  --flavor=woff2 \
  --unicodes=U+0000-00FF

A full Inter variable font is ~300KB; Latin-only subset is ~30KB.

Variable Fonts

One file replaces multiple weight/style files:

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-var.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
 
h1 { font-weight: 700; }
p  { font-weight: 400; }

Fallback Font Matching

Reduce CLS from font swap by matching fallback metrics:

@font-face {
  font-family: 'Inter Fallback';
  src: local('Arial');
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
  size-adjust: 107%;
}
 
body {
  font-family: 'Inter', 'Inter Fallback', sans-serif;
}

size-adjust and the override properties fine-tune the system font to match the web font's metrics, preventing text reflow on swap.

Measuring Impact

MetricWhat It MeasuresTarget
LCPLargest Contentful Paint (usually hero image)< 2.5s
CLSCumulative Layout Shift (image/font reflow)< 0.1
Total WeightPage bytes transferred< 1MB first load
Image Weight% of total bytes from imagesMinimize with modern formats

Interview Signal

Senior candidates demonstrate:

  1. Format fluency — AVIF > WebP > JPEG chain, when to use each, browser negotiation
  2. Loading strategy — fetchpriority for LCP images, loading="lazy" for below-fold, explicit dimensions for CLS
  3. Font optimization — font-display, preloading, subsetting, variable fonts, fallback metric matching
  4. Video awareness — Facade pattern, codec selection, replacing GIFs with muted video
  5. Measurement — Connecting optimizations to Core Web Vitals metrics, not just "smaller files"