Use <picture> with an <img> fallback
Every <picture> element contains a required <img> fallback as its last child, ensuring images display in all browsers including those that don't support <picture>.
- Every `<picture>` must end with an `<img>` element—it is the required fallback and carries `alt`
- `<source>` elements are evaluated top-to-bottom; the first match wins
- Use `type="image/avif"` and `type="image/webp"` on `<source>` for format selection
- The `<img src>` should point to a JPEG or PNG—the universal fallback for all browsers
Rule Details
The <picture> element provides two capabilities: serving different image formats to different browsers (format selection), and serving different image crops at different viewport sizes (art direction). In both cases, the <img> child is required.
Code Example
<!-- ❌ Bad: No <img> fallback — renders nothing if no <source> matches -->
<picture>
<source type="image/avif" srcset="photo.avif">
<source type="image/webp" srcset="photo.webp">
</picture>
<!-- ✅ Good: <img> is last child and carries alt, width, height -->
<picture>
<source type="image/avif" srcset="photo.avif">
<source type="image/webp" srcset="photo.webp">
<img
src="photo.jpg"
alt="Mountain landscape at dawn"
width="800"
height="600"
loading="lazy"
>
</picture>Why It Matters
A <picture> without an <img> fallback renders nothing in browsers that don't support <picture> (IE11) or don't support any of the <source> formats. The <img> child is also where alt, width, height, loading, and fetchpriority attributes live—these apply regardless of which source the browser selects.
Use Case 1: Format Selection
Serve the smallest supported format using the type attribute on <source>.
<!-- Browser picks the first <source> whose type it supports -->
<picture>
<!-- AVIF: best compression (~40-50% smaller than JPEG) -->
<source type="image/avif" srcset="photo.avif">
<!-- WebP: broad support (~25-35% smaller than JPEG) -->
<source type="image/webp" srcset="photo.webp">
<!-- JPEG: universal fallback -->
<img src="photo.jpg" alt="Mountain landscape at dawn" width="800" height="600">
</picture>Use Case 2: Art Direction
Serve different crops or aspect ratios at different viewport sizes using the media attribute.
<!-- Different image crops for different breakpoints -->
<picture>
<!-- Mobile: portrait crop (1:1) -->
<source
media="(max-width: 480px)"
srcset="hero-square-480.webp"
type="image/webp"
>
<!-- Tablet: 4:3 crop -->
<source
media="(max-width: 1024px)"
srcset="hero-4x3-1024.webp"
type="image/webp"
>
<!-- Desktop: wide banner (16:9) -->
<img
src="hero-wide-1600.jpg"
alt="Company team photo"
width="1600"
height="900"
fetchpriority="high"
>
</picture>Use Case 3: Format + Responsive Combined
Combine type and srcset with sizes for the most complete implementation.
<picture>
<source
type="image/avif"
srcset="
photo-400.avif 400w,
photo-800.avif 800w,
photo-1200.avif 1200w
"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 600px"
>
<source
type="image/webp"
srcset="
photo-400.webp 400w,
photo-800.webp 800w,
photo-1200.webp 1200w
"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 600px"
>
<img
src="photo-800.jpg"
srcset="
photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w
"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 600px"
alt="Photo description"
width="1200"
height="800"
loading="lazy"
>
</picture>source Element Order
Browser evaluates <source> elements top-to-bottom and uses the first match. Always put the most preferred (smallest, best quality) format first.
<picture>
<!-- ✅ Correct order: AVIF first (smallest), then WebP, then <img> (JPEG) -->
<source type="image/avif" srcset="photo.avif">
<source type="image/webp" srcset="photo.webp">
<img src="photo.jpg" alt="...">
<!-- ❌ Wrong order: WebP before AVIF means AVIF-supporting browsers get WebP -->
<!-- <source type="image/webp" srcset="photo.webp"> -->
<!-- <source type="image/avif" srcset="photo.avif"> -->
<!-- <img src="photo.jpg" alt="..."> -->
</picture>Attributes Belong on img, Not source
alt, loading, fetchpriority, decoding, width, and height must be on the <img> element.
<!-- ❌ Bad: Attributes on <source> are ignored -->
<picture>
<source type="image/webp" srcset="photo.webp" alt="Photo" loading="lazy">
<img src="photo.jpg">
</picture>
<!-- ✅ Good: Attributes on <img> apply regardless of which source is used -->
<picture>
<source type="image/webp" srcset="photo.webp">
<img
src="photo.jpg"
alt="Photo description"
width="800"
height="600"
loading="lazy"
decoding="async"
>
</picture>Support Notes
- Image format and delivery behavior can vary by browser, CDN, and device characteristics, so verify the final bytes and rendered output on the supported browser matrix.
- Add a fallback note when a modern format or loading behavior is not available for every required target browser.
Verification
Automated Checks
- Use the W3C Validator — a
<picture>without an<img>child produces an error - In Chrome DevTools → Network → filter by Img — verify the browser selected AVIF or WebP
- Test in Safari (format fallback): Safari added AVIF support in version 16.4; older versions should receive WebP or JPEG
Manual Checks
- Disable JavaScript and reload —
<picture>works entirely without JavaScript
Use with AI
Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.
Check
Verify implementation
Scan all <picture> elements in this codebase. Verify: 1) Every <picture> has an <img> as its last child (required fallback). 2) The <img> has an alt attribute. 3) The <img> has width and height attributes. 4) <source> elements appear before the <img> child. 5) Each <source> has either a srcset attribute or a media attribute. 6) format-selecting <source> elements have a type attribute (type="image/avif", type="image/webp"). Flag any <picture> missing an <img> child or with <img> not as the last child.
Fix
Auto-fix issues
For each <picture> element with issues: 1) If missing <img>: add <img src="{fallback-url}" alt="{description}" width="{w}" height="{h}"> as the last child. 2) If <img> is not last: move it to after all <source> elements. 3) If <source> elements lack type attributes for format selection: add type="image/avif" or type="image/webp". 4) Verify the <img src> points to a universally supported format (JPEG or PNG) as the ultimate fallback. Show the corrected <picture> markup.
Explain
Learn more
Explain how the <picture> element works. Browsers evaluate <source> elements in document order and use the first one whose conditions match (type, media, srcset). The <img> element is the fallback for browsers that don't support <picture> (IE11) or don't support the source format. Without an <img> child, <picture> is invalid HTML and produces no output. The alt attribute must be on the <img>, not the <source> elements—it applies regardless of which source is selected.
Review
Code review
Review image assets, markup, and delivery configuration related to Use <picture> with an <img> fallback. Flag exact files or components where format choice, sizing, or loading behavior violates the rule, and describe how to confirm the fix in DevTools.