The build-time rule
Import an image from src/assets/ and render it with
<Image /> or <Picture /> → Astro optimizes it
at build time: it resizes to a responsive width set, converts to
modern avif/webp, and emits a responsive
srcset + width/height (no CLS) + loading="lazy".
The browser then downloads only the variant it needs.
Images in public/ and plain <img> tags bypass this entirely — they are copied as-is, never optimized.
This matters most for content sites: a raw hero PNG is often the Largest Contentful Paint (LCP) element, and shipping 2 MB to a 360px phone is pure waste.
Before vs after — the payload story
One source image: a 1600×900 hero PNG. On the left it is served raw (what a plain
<img> in public/ ships to every device). On
the right, astro:assets has resized + converted it at build time. Drag
the viewport / DPR below the panels to see which variant the browser picks.
Before — raw <img> in public/ unoptimized
<!-- copied to dist/ verbatim, no srcset, no lazy --> <img src="/hero.png">
After — <Picture> from src/assets/ optimized
<!-- emitted by astro:assets at build (constrained, 1600-wide source) --> <picture> <source type="image/avif" srcset="...640w, ...750w, ...800w, ...828w, ...1080w, ...1280w, ...1600w"> <source type="image/webp" srcset="...640w, ...750w, ...800w, ...828w, ...1080w, ...1280w, ...1600w"> <img src="/_astro/hero.hash.png" width="1600" height="900" loading="lazy" decoding="async" alt="Hero"> </picture>
sizes = (min-width: 800px) 800px, 100vw → effective display width = 320 px → needs ≈ 320 device px640w · avif 70 KB · webp 115 KB · vs raw 2048 KB → save 97%
The optimized variant set (the curated demo data)
These are the exact widths the Astro docs show for a
constrained layout on a 1600-wide source. Per-variant sizes are a
deterministic simulation (a single .html cannot run Sharp): webp ≈
width × 0.18 KB, avif ≈ width × 0.11 KB. The optimizer
caps at the source width and never upscales.
Comparison — <Image> vs <Picture> vs plain <img>
src/, render
with <Image/>/<Picture/>, get resize + avif/webp +
responsive srcset + lazy at build time. Cross-refs:
🔗 astro_content_collections (collection image() schema wires cover images into this optimizer) ·
🔗 astro_islands (content is static HTML — image work happens at build, not in JS).