Skip to content
Astro as images 4 min read

The Image Component

The <Image /> component is Astro’s built-in answer to image optimization. Instead of shipping raw, oversized files and writing fragile <img> markup by hand, you import an image and let Astro transform it at build time: it converts to modern formats like WebP and AVIF, generates correctly sized files, and emits markup that prevents layout shift. It lives in the astro:assets module and works for both local files and remote URLs, all with zero client-side JavaScript.

Importing and basic usage

<Image /> is imported from astro:assets, a virtual module that ships with Astro. For local images, you also import the image itself as an ES module — this gives Astro the metadata (intrinsic width, height, format) it needs to optimize the file.

---
import { Image } from "astro:assets";
import rocket from "../assets/rocket.png";
---

<Image src={rocket} alt="A rocket launching into orbit" />

Because you imported rocket, Astro already knows its dimensions and can infer width and height automatically. The generated <img> includes those attributes plus loading="lazy" and decoding="async" by default, so images below the fold don’t block rendering.

The alt attribute is required on <Image />. If the image is purely decorative, pass an empty string (alt="") — omitting it entirely is a build error. This enforces accessibility by default.

Required and core attributes

AttributeRequiredDescription
srcYesAn imported image, an import path, or a remote URL string.
altYesAlternative text; use "" for decorative images.
width / heightFor remote/inlineInferred automatically for imported local images.
formatNoOutput format: webp (default), avif, png, jpeg, svg.
qualityNolow, mid, high, max, or a number 0–100.
densitiesNoPixel densities for the srcset (e.g. [1.5, 2]).
widthsNoExplicit widths for a responsive srcset.
loadingNolazy (default) or eager for above-the-fold images.

Resizing and format control

You rarely want to serve an image at its full intrinsic resolution. Pass width (and optionally height) to downscale; Astro preserves the aspect ratio when only one is given. You can also force an output format and tune quality.

---
import { Image } from "astro:assets";
import hero from "../assets/hero.jpg";
---

<Image
  src={hero}
  alt="Mountain landscape at dawn"
  width={800}
  format="avif"
  quality="high"
/>

Here a large JPEG is resized to 800px wide and re-encoded as AVIF at high quality. Astro writes the optimized file into the build output and rewrites src to point at it. Importantly, Astro will never upscale a local image beyond its intrinsic dimensions — requesting a width larger than the source simply yields the original size.

Optimizing for high-density displays

To serve sharper images on Retina-class screens, use densities. Astro generates a srcset with the requested pixel ratios so browsers pick the right file.

---
import { Image } from "astro:assets";
import avatar from "../assets/avatar.png";
---

<Image src={avatar} alt="User avatar" width={120} densities={[1.5, 2]} />

This produces three candidate sources (1x, 1.5x, 2x) at 120, 180, and 240 CSS pixels respectively, letting high-DPI devices fetch crisper assets while standard displays download the smaller file.

Remote images

You can pass a URL string to src, but Astro needs explicit width and height because it cannot read remote files at build time to infer them. By default Astro only optimizes images from your own domain — to optimize images from other hosts you must allow them in your config.

// astro.config.mjs
import { defineConfig } from "astro/config";

export default defineConfig({
  image: {
    domains: ["images.unsplash.com"],
    // or use remotePatterns for wildcard matching
    remotePatterns: [{ protocol: "https" }],
  },
});
---
import { Image } from "astro:assets";
---

<Image
  src="https://images.unsplash.com/photo-123"
  alt="Remote photo"
  width={600}
  height={400}
/>

How optimization works

By default, image processing uses Sharp, a fast native library. In static (SSG) mode, every transform runs once at build time and the results are emitted as hashed files. In server (SSR) mode, Astro serves optimized images on demand through an endpoint. You can inspect what happened by building locally.

npm run build

Output:

▶ src/pages/index.astro
  └─ /_astro/hero.Ck3p9d.avif (image) (+1)
  generating optimized images
  ▶ /_astro/hero.Ck3p9d.avif
    └─ Completed in 84ms.

Astro stores optimized images under /_astro/ with content-hashed filenames, which makes them safe to cache forever. The hash changes only when the source or transform options change.

Best Practices

  • Always provide meaningful alt text; use alt="" only for genuinely decorative images.
  • Set loading="eager" on your largest above-the-fold image (the LCP element) and leave the rest lazy.
  • Prefer importing local images so Astro can infer dimensions and prevent cumulative layout shift.
  • Use format="avif" or webp for photographs to cut file size dramatically over PNG/JPEG.
  • Add remote hosts to image.domains or remotePatterns deliberately — don’t open it wider than you need.
  • Specify width to the size you actually render, not the source’s full resolution, to avoid shipping oversized files.
  • Reach for <Picture /> instead when you need multiple <source> formats with explicit fallbacks.
Last updated June 14, 2026
Was this helpful?