How to Use the HTML Picture Element for WebP and AVIF
The picture element lets you serve AVIF to modern browsers, WebP to slightly older ones, and JPEG to ancient ones, all in one HTML block. Here is the syntax.
The <picture> element is the cleanest way to serve modern image formats with safe fallback. One block of HTML, every browser gets the best format it can render. Here's how it works and the template you can copy.
The basic syntax
<picture>
<source srcset="hero.avif" type="image/avif">
<source srcset="hero.webp" type="image/webp">
<img src="hero.jpg" alt="Sunset over the mountains" width="1600" height="900">
</picture>
The browser walks through the <source> elements in order. The first one it can render wins. If none of them are supported (ancient browser), it falls back to the <img> inside.
The width and height attributes on <img> are NOT optional in 2026: they prevent layout shift (CLS).
Why the order matters
AVIF first, then WebP, then JPEG. The browser stops at the first format it supports. A Safari 16 browser supports AVIF, so it never even sees the WebP source. A Firefox 80 browser doesn't support AVIF, sees WebP, stops there.
If you swap the order (WebP first, then AVIF) every modern browser uses WebP and you wasted the work of encoding to AVIF.
Adding responsive sizes
You almost always want different image sizes for different viewports. The srcset attribute does that within each <source>:
<picture>
<source
srcset="hero-400.avif 400w, hero-800.avif 800w, hero-1600.avif 1600w"
sizes="(max-width: 600px) 100vw, 50vw"
type="image/avif">
<source
srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1600.webp 1600w"
sizes="(max-width: 600px) 100vw, 50vw"
type="image/webp">
<img
src="hero-800.jpg"
srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw, 50vw"
alt="Sunset"
width="1600" height="900">
</picture>
The browser picks the right size based on sizes (a CSS-like media query that tells it how wide the image will display) and the viewport width.
Art direction with media queries
<picture> can also serve completely different images at different breakpoints, useful when a landscape hero needs to become a portrait crop on mobile:
<picture>
<source media="(max-width: 600px)" srcset="hero-portrait.avif" type="image/avif">
<source media="(min-width: 601px)" srcset="hero-landscape.avif" type="image/avif">
<img src="hero-landscape.jpg" alt="..." width="1600" height="900">
</picture>
Different media queries lead to different source images, not just different sizes of the same image.
Browser support
<picture> is supported in every browser version since 2015. There's no compatibility concern in 2026.
Performance considerations
- Use
loading="lazy"on images below the fold. Don't lazy-load the hero image. It's the LCP candidate. - Use
fetchpriority="high"on the hero image to make sure the browser starts downloading it before any other resource on the page. - Width and height attributes prevent layout shift. The aspect ratio is calculated from them and the slot is reserved before the image loads.
Encoding the sources
To produce the AVIF / WebP / JPEG variants:
- AVIF Converter for AVIF, where quality 60 is the sweet spot.
- PNG to WebP or Image Compressor for WebP, at quality 80.
- Original JPEG (or JPG Compressor at q85) as the fallback.
All conversions run in your browser via WASM, no uploads.
Common mistakes
- Wrong source order. AVIF must come first. WebP next. JPEG fallback last.
- Forgetting
width/heighton the<img>. Causes layout shift and tanks CLS. - Lazy-loading the hero. Delays LCP. Use
loading="eager" fetchpriority="high"instead. - Different aspect ratios across
<source>elements withoutmediaqueries. Browsers may show one ratio, then switch to another on resize, which looks janky. - Forgetting alt text. Accessibility regression and SEO loss for free.
A copy-paste template
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Descriptive alt text"
width="1600" height="900"
loading="lazy" decoding="async">
</picture>
For hero images, change loading="lazy" to loading="eager" and add fetchpriority="high".
Try AVIF Converter, free in your browser
No uploads, no account. Your images never leave your device.
Open AVIF Converter