MegaOptim
Back to Blog Tutorials

How to Serve WebP and AVIF Images with Fallbacks

· 9 min read

How to Serve WebP and AVIF Images with Fallbacks

WebP and AVIF can cut image file sizes by 25-50% compared to JPEG, with no perceptible loss in quality. But adopting these formats is not as simple as replacing every .jpg on your site. Older browsers, email clients, and certain embedded webviews still cannot decode them. If you serve AVIF to a browser that does not support it, your visitors see a broken image icon instead of your content.

The solution is to serve next-gen formats to browsers that support them while falling back to JPEG or PNG for everything else. This article covers the three main approaches to implementing that fallback logic, along with practical code examples you can use today.

For background on these formats themselves, see our guides on WebP and AVIF.

Why Fallbacks Are Necessary

WebP browser support is now excellent, covering over 96% of global users. AVIF, however, tells a different story. While Chrome, Firefox, and Samsung Internet have supported AVIF since 2021-2022, Safari only added full AVIF support in version 16.4 (March 2023). Users on older iOS devices that cannot update past Safari 15 have no AVIF support at all. Internet Explorer, though vanishingly rare, supports neither format.

The practical consequence: if you serve only AVIF, roughly 5-8% of your audience may see broken images. If you serve only JPEG, you leave significant bandwidth savings on the table for the majority who can handle modern formats. The right approach is to serve the best format each browser can handle, automatically.

Approach 1: The HTML Picture Element

The <picture> element is the simplest and most widely recommended approach. It lets you list multiple image sources in order of preference, and the browser picks the first one it supports.

Basic Syntax

<picture>
  <source srcset="hero.avif" type="image/avif">
  <source srcset="hero.webp" type="image/webp">
  <img src="hero.jpg" alt="A mountain landscape at sunrise" width="1200" height="800">
</picture>

The browser evaluates each <source> element from top to bottom. If it supports image/avif, it downloads hero.avif and stops. If not, it checks the next source. The <img> element at the bottom serves as the final fallback and is required — it is also where you place your alt, width, height, loading, and other attributes.

Source Order Matters

Always list your sources from smallest file size to largest:

  1. AVIF first — highest compression, newest format
  2. WebP second — strong compression, broad support
  3. JPEG or PNG last — universal support, largest file

If you reverse the order and put WebP before AVIF, browsers that support both will download the WebP version and never reach the AVIF source, costing you the additional 20-30% savings AVIF typically provides over WebP.

Combining with Responsive Images

The <picture> element works seamlessly with the srcset and sizes attributes for responsive images:

<picture>
  <source
    srcset="hero-480.avif 480w, hero-800.avif 800w, hero-1200.avif 1200w"
    sizes="(max-width: 600px) 480px, (max-width: 1000px) 800px, 1200px"
    type="image/avif">
  <source
    srcset="hero-480.webp 480w, hero-800.webp 800w, hero-1200.webp 1200w"
    sizes="(max-width: 600px) 480px, (max-width: 1000px) 800px, 1200px"
    type="image/webp">
  <img
    src="hero-800.jpg"
    srcset="hero-480.jpg 480w, hero-800.jpg 800w, hero-1200.jpg 1200w"
    sizes="(max-width: 600px) 480px, (max-width: 1000px) 800px, 1200px"
    alt="A mountain landscape at sunrise"
    width="1200" height="800"
    loading="lazy">
</picture>

This gives you the best of both worlds: format negotiation and resolution switching. The markup is verbose, but it delivers the optimal file to every visitor regardless of their browser or screen size.

Approach 2: Server-Side Content Negotiation

When a browser requests an image, it sends an Accept header listing the formats it supports. A browser that handles WebP sends Accept: image/webp,image/*,*/*;q=0.8, and one that handles AVIF includes image/avif in that list. You can configure your web server to inspect this header and serve the appropriate file.

Nginx Configuration

map $http_accept $avif_suffix {
    default   "";
    "~image/avif" ".avif";
}

map $http_accept $webp_suffix {
    default   "";
    "~image/webp" ".webp";
}

location ~* ^(/images/.+).(jpe?g|png)$ {
    # Try AVIF first, then WebP, then original
    try_files $1$avif_suffix $1$webp_suffix $uri =404;
    add_header Vary Accept;
}

This configuration looks for a .avif or .webp version of the requested file on disk. If the browser supports AVIF and hero.jpg.avif exists, Nginx serves it. Otherwise, it falls back to WebP or the original JPEG. The Vary: Accept header is critical — it tells CDNs and caches that the response depends on the Accept header, preventing a cached WebP from being served to a browser that only supports JPEG.

Apache Configuration

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Serve AVIF if supported and file exists
    RewriteCond %{HTTP_ACCEPT} image/avif
    RewriteCond %{REQUEST_FILENAME}.avif -f
    RewriteRule ^(.+).(jpe?g|png)$ $1.$2.avif [T=image/avif,E=ACCEPT:1,L]

    # Serve WebP if supported and file exists
    RewriteCond %{HTTP_ACCEPT} image/webp
    RewriteCond %{REQUEST_FILENAME}.webp -f
    RewriteRule ^(.+).(jpe?g|png)$ $1.$2.webp [T=image/webp,E=ACCEPT:1,L]
</IfModule>

<IfModule mod_headers.c>
    Header append Vary Accept env=ACCEPT
</IfModule>

The server-side approach has one major advantage over the <picture> element: you do not need to change any HTML. Every existing <img src="photo.jpg"> tag continues to work, and the server transparently upgrades the format behind the scenes.

The downside is added server configuration complexity and the requirement that all format variants live on the same server or storage backend with predictable naming conventions.

Approach 3: CDN-Based Automatic Format Selection

Most modern CDNs can handle format negotiation for you, removing the need for server configuration or HTML changes entirely.

Cloudflare offers automatic format conversion through its Polish feature (available on Pro plans and above). When enabled, Cloudflare inspects the visitor’s Accept header and converts images to WebP or AVIF on the fly at the edge. No configuration beyond toggling the feature is needed.

Amazon CloudFront can be paired with Lambda@Edge to inspect the Accept header and rewrite the origin request to fetch the appropriate format variant. AWS also offers CloudFront Functions for lightweight header-based routing.

Imgix, Cloudinary, and similar services accept a format parameter (e.g., ?auto=format) that automatically selects the best format based on browser capabilities.

CDN-based solutions are the lowest-effort option and work well at scale. The tradeoff is vendor lock-in and, depending on the service, additional cost for on-the-fly conversion.

Generating Multiple Format Variants

Whichever delivery approach you choose, you first need the actual WebP and AVIF files. Manually converting images with command-line tools does not scale. The MegaOptim API handles this automatically — you can request WebP and AVIF conversions alongside your optimization in a single API call:

curl -X POST https://api.megaoptim.com/v1/optimize 
  -H "Authorization: Bearer YOUR_API_KEY" 
  -F "[email protected]" 
  -F "compression=intelligent" 
  -F "webp=1" 
  -F "avif=1"

The response includes optimized versions in all three formats (original JPEG, WebP, and AVIF), each compressed using SSIM-guided quality tuning. This gives you the format variants you need for any of the delivery methods described above.

For more details on the API, see our getting started guide.

WordPress Implementation

WordPress added native WebP support in version 5.8 and generates WebP sub-sizes automatically when the server supports it. AVIF support arrived in WordPress 6.5. However, WordPress does not automatically serve these formats with fallbacks — it generates the files but still references the original JPEG in your content.

To serve next-gen formats with proper fallbacks in WordPress, you need a plugin that rewrites image markup to use <picture> elements or configures server-level content negotiation. The MegaOptim WordPress plugin handles both the conversion and delivery sides: it generates WebP and AVIF variants during optimization and rewrites your page output to serve them with appropriate fallbacks.

If you prefer a manual approach, you can use a combination of WordPress filters to modify wp_get_attachment_image output and wrap it in <picture> elements, but this requires careful handling of srcset generation and theme compatibility.

Testing Fallback Behavior

After implementing any of these approaches, verify that fallbacks work correctly:

  1. Chrome DevTools — Open the Network tab, filter by “Img”, and check the Content-Type header of served images. You should see image/avif or image/webp.
  2. Simulate older browsers — In Chrome DevTools, open the Network conditions panel (under the three-dot menu in the Network tab) and modify the Accept header to remove image/avif and image/webp. Reload the page and confirm JPEG/PNG versions are served.
  3. Test in Safari — If you have access to an older version of Safari (pre-16.4), verify that AVIF fallbacks work. BrowserStack or similar cross-browser testing tools can help here.
  4. Validate caching — If you use a CDN, request the same URL from browsers with different Accept headers and confirm the Vary: Accept header is present in the response. Without it, your CDN may cache a single format and serve it to all visitors.

Summary

Serving next-gen image formats with fallbacks is not optional — it is the responsible way to adopt WebP and AVIF without breaking the experience for any visitor. The three approaches each suit different situations:

  • The <picture> element gives you full control in HTML with no server changes, ideal for static sites and hand-crafted pages.
  • Server-side content negotiation works transparently with existing markup, best for sites with large image libraries where changing HTML is impractical.
  • CDN-based solutions offer the least implementation effort and work at global scale, though they introduce third-party dependencies.

In practice, many teams combine these approaches. A CDN handles the bulk of format negotiation, while <picture> elements provide explicit control for critical above-the-fold images. Whichever path you take, the key is ensuring that every visitor gets an image they can render, in the smallest file size their browser supports.