How to configure AVIF fallbacks for Safari 14

The Safari 14 Rendering Constraint

Safari 14 introduced native WebP decoding but excluded AVIF support β€” AVIF arrived in Safari 16. To deliver next-generation compression without degrading UX, implement a strict <picture> cascade that lets the browser pick the best format it supports. For foundational context on progressive image delivery, see Core Media Fundamentals & Next-Gen Formats before deploying pipeline changes.

Exact HTML Implementation & Server Routing

Browsers evaluate <source> elements sequentially and stop at the first supported type. Safari 14 skips image/avif, matches image/webp, and falls through to the <img> element only if both fail. Ensure your origin or edge server returns Vary: Accept so CDN nodes cache variants separately. Cross-reference your encoding parameters with AVIF vs WebP Compression Benchmarks before rolling out to production.

HTML Structure

<picture>
  <!-- AVIF: served to Safari 16+, Chrome 85+, Firefox 93+ -->
  <source srcset="/img/hero.avif" type="image/avif">
  <!-- WebP: fallback for Safari 14–15 and older Chromium -->
  <source srcset="/img/hero.webp" type="image/webp">
  <!-- JPEG: universal fallback -->
  <img src="/img/hero.jpg" alt="Hero visual" width="800" height="450"
       loading="eager" fetchpriority="high">
</picture>

Nginx Server Configuration

location ~* \.(avif|webp|jpg|jpeg|png)$ {
    # Critical: instructs CDNs to cache per Accept header
    add_header Vary Accept;

    # Explicit MIME mapping prevents fallback to application/octet-stream
    types {
        image/avif avif;
        image/webp webp;
        image/jpeg jpg jpeg;
        image/png png;
    }

    # Long-term caching for fingerprinted static assets
    add_header Cache-Control "public, max-age=31536000, immutable";
    expires 1y;
    try_files $uri =404;
}

Validation, Metrics & Debugging

Verify format negotiation using CLI tools and synthetic testing. If Safari 14 displays broken images, trace the Accept header chain, confirm MIME type registration, and verify CDN Vary configuration.

CLI Validation Steps

# 1. Verify AVIF delivery for modern browsers
curl -sI -H 'Accept: image/avif,image/webp,image/*,*/*;q=0.8' \
  https://yourdomain.com/img/hero.jpg | grep -i 'content-type'

# 2. Verify WebP fallback for Safari 14
curl -sI -H 'Accept: image/webp,image/*,*/*;q=0.8' \
  https://yourdomain.com/img/hero.jpg | grep -i 'content-type'

# 3. Measure LCP using Lighthouse CLI
lighthouse https://yourdomain.com \
  --only-categories=performance --output=json \
  | jq '.audits["largest-contentful-paint"].displayValue'

Expected Metric Deltas

Metric Expected Delta Implementation Note
LCP Improvement –18% to –32% vs baseline JPEG Dependent on fetchpriority="high" and preload strategy
Payload Reduction –22% to –40% AVIF typically outperforms WebP by 15–20% at equal SSIM
Cache Efficiency +15% edge hit rate with correct Vary: Accept Prevents cache collision across browser versions
Safari 14 Fallback Latency <50ms additional TTFB WebKit’s WebP decoder initializes quickly

Failure Recovery Paths

  • Safari 14 displays broken image icon

    • Root cause: Missing type attribute or incorrect MIME mapping on origin.
    • Fix: Verify the types block in Nginx/Apache config includes image/webp webp;. Test with curl -H 'Accept: image/webp'.
  • CDN serves AVIF to Safari 14

    • Root cause: Missing Vary: Accept causing cache collision.
    • Fix: Purge CDN cache. Add add_header Vary Accept; to the server block. Verify edge cache keys include the Accept header.
  • LCP degrades after implementation

    • Root cause: Fallback JPEG lacks fetchpriority="high" or the <picture> block stalls parsing.
    • Fix: Add fetchpriority="high" to the <img> tag. Preload the critical AVIF via <link rel="preload" as="image" type="image/avif" href="/img/hero.avif"> targeting modern browsers with a media or JS check.