komal.nakrani
Browse Themes
ThemesCategoriesDocsBlogTips & Tricks
Performance••By Komal Nakrani

Astro Image vs Picture vs a Plain img Tag

Astro Image vs Picture vs img: use Image for most local images, Picture when you want AVIF with a WebP fallback, and img for CMS-CDN, SVG or public files.

#Astro#Decision Guide#Images

For Astro image vs Picture: use <Image /> for nearly every local image. It resizes, converts to WebP, sets dimensions and lazy-loads. Use <Picture /> when you want several formats, typically AVIF with a WebP fallback, on large images where the extra savings matter. Use a plain <img> when something else already optimises the image (a CMS image CDN), for SVG icons, or for files in public/ you don’t want processed.

Key Takeaways

  • <Image />: one optimised format, responsive srcset, no layout shift. The default choice.
  • <Picture />: multiple formats via <source> elements. Best for heroes and large photos.
  • Plain <img>: when optimisation happens elsewhere, or for SVG and tiny decorative assets.
  • getImage(): when you need the URL rather than markup (CSS backgrounds, Open Graph).

Decision flow

  1. Is the image served by a CMS or image CDN that already resizes it? Yes → plain <img> with the CDN’s parameters.
  2. Is it an SVG? Yes → inline it, import it as a component, or use <img>. Raster processing doesn’t help.
  3. Do you need the URL, not an element? (CSS background, meta tag) → getImage().
  4. Is it a large photo where AVIF savings matter? (hero, full-width banner) → <Picture formats={['avif', 'webp']} />.
  5. Otherwise → <Image />.

Compared

<Image /> <Picture /> <img>
Output <img> <picture> + <source>s + <img> As written
Formats One (WebP default) Several Whatever the file is
Responsive srcset With layout or widths With layout or widths Write it yourself
Dimensions set Yes Yes Only if you add them
Lazy loading Default Default Add loading="lazy"
Build cost One encode per width One per width per format None
Works with public/ files Needs dimensions; not optimised Same Yes

Examples

---
import { Image, Picture } from 'astro:assets';
import hero from '../assets/hero.jpg';
import avatar from '../assets/avatar.jpg';
import logo from '../assets/logo.svg';
---
<!-- Hero: worth the extra AVIF encode -->
<Picture src={hero} formats={['avif', 'webp']} alt="Product dashboard" layout="full-width" priority />

<!-- Ordinary content image -->
<Image src={avatar} alt="Anika Rao" width={96} height={96} densities={[1, 2]} />

<!-- SVG logo -->
<img src={logo.src} width={logo.width} height={logo.height} alt="Acme" />

<!-- CMS image with its own CDN -->
<img src={`${cover.url}?w=1200&fm=webp`} width={1200} height={630} alt={cover.alt} loading="lazy" />

Things to know

  • AVIF encoding is slower than WebP. On image-heavy sites, <Picture /> everywhere can noticeably lengthen builds; see faster Astro builds in CI.
  • Markdown images (![alt](./img.jpg)) are optimised like <Image /> automatically.
  • priority goes on one image per page: the LCP image.
  • Images in public/ aren’t processed by any of the three. Move them to src/ to optimise them.

Every prop is listed in the image props cheatsheet, and sizing is explained in responsive images in Astro. For the performance impact, see the Astro performance guide. The official images guide covers every component.

FAQ

Is Picture always better than Image?

No. It produces more files and slower builds. Use it where the format savings are worth it, usually large images.

Can Image output AVIF?

Yes, with format="avif", but then browsers without AVIF support get nothing better. <Picture /> provides a fallback.