The picture element and fallback formats
picture lets you serve the most efficient format to each browser without leaving anyone without an image. It's the key to using AVIF safely today.
What picture is for
<picture> wraps an <img> and adds a list of alternative sources. The browser walks through the <source> elements in order and uses the first one that matches (supported file type and media query). If none matches, it uses the <img>.
It has two main uses:
- Format switching: serve AVIF or WebP to browsers that support them and JPEG to the rest.
- Art direction: show a different crop depending on screen size (for example, a portrait crop on mobile).
Format switching
<picture>
<source type="image/avif" srcset="product.avif">
<source type="image/webp" srcset="product.webp">
<img src="product.jpg" width="1200" height="1200" alt="Blue running shoe, side view">
</picture>
Key points:
- The
typeattribute is what lets the browser skip a source without downloading it. Without it, the browser might fetch a file it can't display. - Order goes from most efficient to most compatible.
- The final
<img>is required: it's what's actually rendered and it carriesalt,width,height,loadingandfetchpriority.
A browser that supports AVIF downloads only product.avif. It never downloads several sources for the same image.
Styles and attributes: always on the img
A common mistake is applying classes or attributes to <picture> or the <source> elements. In most cases <picture> doesn't render as its own box; the <img> is what takes up space. So:
- Sizing CSS classes,
object-fit, borders and so on go on the<img>. alt,width,height,loading,decodingandfetchprioritygo on the<img>.<source>elements only carrytype,srcset,sizesandmedia.
Combining formats and sizes
Each <source> accepts srcset and sizes, so you can offer several widths in each format:
<picture>
<source type="image/avif"
srcset="hero-960.avif 960w, hero-1920.avif 1920w"
sizes="100vw">
<source type="image/webp"
srcset="hero-960.webp 960w, hero-1920.webp 1920w"
sizes="100vw">
<img src="hero-1920.jpg"
srcset="hero-960.jpg 960w, hero-1920.jpg 1920w"
sizes="100vw"
width="1920" height="800" alt="…" fetchpriority="high">
</picture>
ImageZap generates exactly this markup: enable several formats and responsive variants, open Code on any image and copy the result.
Art direction with media
If you want a different crop on mobile, use media:
<picture>
<source media="(max-width: 640px)" srcset="banner-portrait.avif" type="image/avif">
<source media="(max-width: 640px)" srcset="banner-portrait.jpg">
<source srcset="banner-landscape.avif" type="image/avif">
<img src="banner-landscape.jpg" width="1600" height="600" alt="…">
</picture>
Note that if the aspect ratio changes, the <img>'s width and height only describe the desktop version. Modern browsers let you put width and height on each <source> too, so the right space is reserved in every case.
What about CSS background images?
For backgrounds, the image-set() function plays the same role:
.hero {
background-image: url("hero.jpg");
background-image: image-set(
url("hero.avif") type("image/avif"),
url("hero.webp") type("image/webp"),
url("hero.jpg") type("image/jpeg")
);
}
The first declaration is a fallback for browsers that don't understand image-set() with type(). Remember that background images are discovered late: if it's the LCP image, add a <link rel="preload">.
Frequently asked questions
Does picture affect SEO?
Not negatively. Google indexes the <img>'s image and also understands the alternative sources. The <img>'s alt is what counts.
Can I put JPEG XL in picture?
Yes, as the first source. Safari will use it and other browsers will move on to the next one. Make sure to include type="image/jxl".
Do I need picture if I only use WebP?
If your audience uses modern browsers, an <img src="photo.webp"> is enough. picture is needed when you combine formats or do art direction.
What about lazy loading?
It works the same: put loading="lazy" on the <img> (except on the main image).