AVIF (AV1 Image File Format) is derived from the AV1 video codec, developed by the Alliance for Open Media. It delivers the best quality-to-size ratio among current web image formats, outperforming both WebP and JPEG in most scenarios.
Web image format comparison
| Format | Year | Compression | Transparency | HDR | Animation | Browser support |
|---|---|---|---|---|---|---|
| JPEG | 1992 | Good | No | No | No | 100 % |
| PNG | 1996 | Lossless | Yes | No | No | 100 % |
| WebP | 2010 | Very good | Yes | No | Yes | 96 % |
| AVIF | 2019 | Excellent | Yes | Yes | Yes | 93 % |
| JPEG XL | 2022 | Excellent | Yes | Yes | Yes | ~30 % |
AVIF typically achieves files 30β50 % smaller than WebP at equivalent quality, and up to 80 % smaller than JPEG.
Browser support (2024)
Chrome 85+ β
native
Firefox 93+ β
native
Safari 16+ β
native (macOS Ventura / iOS 16)
Edge 121+ β
native
Opera 71+ β
native
IE 11 β no support
At 93 % coverage, AVIF is production-safe with WebP/JPEG fallback.
HTML with progressive fallback
<!-- Fallback: AVIF β WebP β JPEG -->
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Description" width="800" height="600">
</picture>
<!-- Responsive srcset -->
<picture>
<source
srcset="image-400.avif 400w, image-800.avif 800w, image-1200.avif 1200w"
sizes="(max-width: 600px) 400px, (max-width: 900px) 800px, 1200px"
type="image/avif">
<source
srcset="image-400.webp 400w, image-800.webp 800w, image-1200.webp 1200w"
sizes="(max-width: 600px) 400px, (max-width: 900px) 800px, 1200px"
type="image/webp">
<img src="image-800.jpg" alt="Description" loading="lazy">
</picture>
Converting with FFmpeg
FFmpeg β₯ 4.3 includes AVIF support via the libaom-av1 codec:
# JPEG/PNG β AVIF basic conversion
ffmpeg -i input.jpg -c:v libaom-av1 -crf 30 -b:v 0 output.avif
# Quality control (CRF: 0=best quality, 63=worst)
# Recommended range: 20β40
ffmpeg -i input.png -c:v libaom-av1 -crf 23 -b:v 0 output.avif
# Encoding speed (cpu-used: 0=slow/best, 8=fast/worst)
# Production: 4β6. Max quality: 0β2
ffmpeg -i input.jpg \
-c:v libaom-av1 \
-crf 28 \
-b:v 0 \
-cpu-used 4 \
-row-mt 1 \
output.avif
# PNG with transparency
ffmpeg -i logo.png -c:v libaom-av1 -crf 25 -b:v 0 logo.avif
Converting with Pillow (Python)
# pip install pillow
# Pillow >= 9.1.0 includes native AVIF support on most platforms
from PIL import Image
# Open and save as AVIF
img = Image.open('image.jpg')
img.save('image.avif', format='AVIF', quality=80)
# quality: 0-100 (100 = best quality, largest file)
# Check AVIF support
from PIL import features
print(features.check_codec('avif')) # True if available
# Convert with max width and quality control
def jpg_to_avif(input_path, output_path, quality=75, max_width=1920):
img = Image.open(input_path)
if img.width > max_width:
ratio = max_width / img.width
new_height = int(img.height * ratio)
img = img.resize((max_width, new_height), Image.LANCZOS)
img.save(output_path, format='AVIF', quality=quality)
return output_path
jpg_to_avif('photo.jpg', 'photo.avif', quality=80)
Batch conversion with Python
import os
from pathlib import Path
from PIL import Image
def convert_directory_to_avif(directory, quality=78):
source = Path(directory)
extensions = {'.jpg', '.jpeg', '.png', '.webp'}
results = []
for file in sorted(source.iterdir()):
if file.suffix.lower() not in extensions:
continue
dest = file.with_suffix('.avif')
try:
img = Image.open(file)
img.save(dest, format='AVIF', quality=quality)
orig_size = os.path.getsize(file)
avif_size = os.path.getsize(dest)
savings = (1 - avif_size / orig_size) * 100
results.append({
'file': file.name,
'original_kb': orig_size // 1024,
'avif_kb': avif_size // 1024,
'savings_pct': round(savings, 1),
})
print(f"OK: {file.name} β {orig_size//1024}KB β {avif_size//1024}KB ({savings:.0f}% smaller)")
except Exception as e:
print(f"ERROR: {file.name}: {e}")
return results
stats = convert_directory_to_avif('images/')
avg_savings = sum(r['savings_pct'] for r in stats) / len(stats) if stats else 0
print(f"\nAverage savings: {avg_savings:.1f}%")
Quality settings by use case
| Use case | CRF (ffmpeg) | quality (Pillow) | Notes |
|---|---|---|---|
| Web photography | 30β35 | 70β80 | Size/quality balance |
| Thumbnails | 38β45 | 55β65 | Prioritize small size |
| Product images | 22β28 | 82β90 | Maximum perceived quality |
| Hero / banner | 32β38 | 65β75 | Users rarely inspect closely |
| Icons / graphics | 18β25 | 85β95 | No perceptible loss |
AVIF in Next.js / Astro
// next.config.js β enable automatic AVIF
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
},
}
// Next.js converts and serves AVIF automatically with <Image>
// Astro β built-in AVIF via Sharp
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
image: { service: { entrypoint: 'astro/assets/services/sharp' } }
});
When to use AVIF
Use AVIF for:
- Photography and rich-color images on modern sites
- Sites where performance and Core Web Vitals are priorities
- Hero images, galleries, and product pages
Always add WebP + JPEG fallback using <picture> for browsers without support, especially Safari < 16 and iOS < 16.