patternjavascriptModerate
Image optimization pipeline: WebP and AVIF with fallback using picture element
Viewed 0 times
AVIFWebPimage optimizationsharppicture elementnext-gen imagesimage-set
Problem
Images are the largest contributor to page weight in most web applications. Serving JPEG/PNG to all browsers instead of next-generation formats like AVIF wastes 40-80% of image file size.
Solution
Use the <picture> element to serve AVIF to browsers that support it, WebP as a fallback, and JPEG/PNG for legacy browsers.
<picture>
<source type="image/avif" srcset="/photo.avif" />
<source type="image/webp" srcset="/photo.webp" />
<img src="/photo.jpg" alt="Photo" width="800" height="600" />
</picture>
// Build pipeline: generate variants with sharp
const sharp = require('sharp');
async function optimizeImage(inputPath, outputDir) {
const base = path.basename(inputPath, path.extname(inputPath));
await sharp(inputPath).webp({ quality: 80 }).toFile(
await sharp(inputPath).avif({ quality: 60 }).toFile(
// Keep original JPEG as fallback
}
<picture>
<source type="image/avif" srcset="/photo.avif" />
<source type="image/webp" srcset="/photo.webp" />
<img src="/photo.jpg" alt="Photo" width="800" height="600" />
</picture>
// Build pipeline: generate variants with sharp
const sharp = require('sharp');
async function optimizeImage(inputPath, outputDir) {
const base = path.basename(inputPath, path.extname(inputPath));
await sharp(inputPath).webp({ quality: 80 }).toFile(
${outputDir}/${base}.webp);await sharp(inputPath).avif({ quality: 60 }).toFile(
${outputDir}/${base}.avif);// Keep original JPEG as fallback
}
Why
AVIF offers 40-50% smaller files than JPEG at equivalent quality. WebP offers 25-35% savings. Browser support: AVIF is supported in Chrome 85+, Firefox 93+, Safari 16+. WebP is universally supported in modern browsers. The picture element ensures graceful fallback.
Gotchas
- AVIF encoding is slow at build time — cache generated files and only regenerate when the source changes
- AVIF quality 60 is roughly equivalent to JPEG quality 80 — don't apply the same quality numbers across formats
- CDN image transformation services (Cloudinary, Imgix, Cloudflare Images) can auto-serve AVIF/WebP based on Accept header
- CSS background-image cannot use <picture> — use image-set() CSS function for format selection in CSS
Code Snippets
CSS image-set for format negotiation in background images
/* image-set for CSS background images */
.hero {
background-image: image-set(
url('/hero.avif') type('image/avif'),
url('/hero.webp') type('image/webp'),
url('/hero.jpg') type('image/jpeg')
);
background-size: cover;
}Context
When auditing image weight in Lighthouse or building an image processing pipeline
Revisions (0)
No revisions yet.