Images
Astro provides several ways for you to use images on your site, whether they are stored locally inside your project, linked to from an external URL, or managed in a CMS or CDN!
Where to store images
Section titled Where to store imagessrc/
vs public/
Section titled src/ vs public/We recommend that local images are kept in src/
when possible so that Astro can transform, optimize and bundle them. Files in the /public
directory are always served or copied into the build folder as-is, with no processing.
Your local images stored in src/
can be used by all files in your project: .astro
, .md
, .mdx
, .mdoc
, and other UI frameworks. Images can be stored in any folder, including alongside your content.
Store your images in the public/
folder if you want to avoid any processing or to have a direct public link to them.
Remote images
Section titled Remote imagesYou can also choose to store your images remotely, in a content management system (CMS) or digital asset management (DAM) platform.
For extra protection when dealing with external sources, remote images will only be processed from authorized image sources specified in your configuration. However, any remote images can be displayed.
Astro can fetch your data remotely using APIs or display images from their full URL path. See our CMS guides for examples of integrating common services.
Images in .astro
files
Section titled Images in .astro filesIn .astro
files, local images must be imported into the file in order to be used. Remote and public/
images do not require importing.
Import and use Astro’s built-in <Image />
component for optimized images using astro:assets
. Alternatively, Astro syntax supports writing an HTML <img>
tag directly, which skips image processing.
---import { Image } from 'astro:assets';import localBirdImage from '../../images/subfolder/localBirdImage.png';---<Image src={localBirdImage} alt="A bird sitting on a nest of eggs." /><Image src="/images/bird-in-public-folder.jpg" alt="A bird." width="50" height="50" /><Image src="https://example.com/remote-bird.jpg" alt="A bird." width="50" height="50" />
<img src={localBirdImage.src} alt="A bird sitting on a nest of eggs."><img src="/images/bird-in-public-folder.jpg" alt="A bird."><img src="https://example.com/remote-bird.jpg" alt="A bird.">
To dynamically import images from the src/
folder, see the following recipe:
![](/houston_chef.webp)
<Image />
(astro:assets
)
Section titled <Image /> (astro:assets)Use the built-in <Image />
Astro component to display optimized versions of your local images and configured remote images.
Images in the public/
folder, as well as remote images not specifically configured in your project, can also be used with the Image component, but will not be processed.
<Image />
can transform a local or authorized remote image’s dimensions, file type, and quality for control over your displayed image. The resulting <img>
tag includes alt
, loading
, and decoding
attributes and infers image dimensions to avoid Cumulative Layout Shift (CLS).
Cumulative Layout Shift (CLS) is a Core Web Vital metric for measuring how much content shifted on your page during loading. The <Image />
component optimizes for CLS by automatically setting the correct width
and height
for your local images.
---// import the Image component and the imageimport { Image } from 'astro:assets';import myImage from '../assets/my_image.png'; // Image is 1600x900---
<!-- `alt` is mandatory on the Image component --><Image src={myImage} alt="A description of my image." />
<!-- Output --><!-- Image is optimized, proper attributes are enforced --><img src="/_astro/my_image.hash.webp" width="1600" height="900" decoding="async" loading="lazy" alt="A description of my image."/>
Properties
Section titled Propertiessrc (required)
Section titled src (required)The format of the src
value of your image file depends on where your image file is located:
-
Local images in
src/
- you must also import the image using a relative file path or configure and use an import alias. Then use the import name as thesrc
value:src/pages/index.astro ---import { Image } from 'astro:assets';import myImportedImage from '../assets/my-local-image.png';---<Image src={myImportedImage} alt="descriptive text" /> -
Images in the
public/
folder - use the image’s file path relative to the public folder:src/pages/index.astro ---import { Image } from 'astro:assets';---<Imagesrc="/images/my-public-image.png"alt="descriptive text"width="200"height="150"/> -
Remote images - use the image’s full URL as the property value:
src/pages/index.astro ---import { Image } from 'astro:assets';---<Imagesrc="https://example.com/remote-image.jpg"alt="descriptive text"width="200"height="150"/>
alt (required)
Section titled alt (required)Use the required alt
attribute to provide a string of descriptive alt text for images.
If an image is merely decorative (i.e. doesn’t contribute to the understanding of the page), set alt=""
so that screen readers and other assistive technologies know to ignore the image.
width and height (required for images in public/
)
Section titled width and height (required for images in public/)These properties define the dimensions to use for the image.
When using images in their original aspect ratio, width
and height
are optional. These dimensions can be automatically inferred from image files located in src/
and from remote images with inferSize
set to true
.
However, both of these properties are required for images stored in your public/
folder as Astro is unable to analyze these files.
densities
Section titled densities
Added in:
astro@3.3.0
A list of pixel densities to generate for the image.
If provided, this value will be used to generate a srcset
attribute on the <img>
tag. Do not provide a value for widths
when using this value.
Densities that are equal to widths larger than the original image will be ignored to avoid upscaling the image.
---import { Image } from 'astro:assets';import myImage from '../assets/my_image.png';---<Image src={myImage} width={myImage.width / 2} densities={[1.5, 2]} alt="A description of my image."/>
<!-- Output --><img src="/_astro/my_image.hash.webp" srcset=" /_astro/my_image.hash.webp 1.5x /_astro/my_image.hash.webp 2x " alt="A description of my image." width="800" height="450" loading="lazy" decoding="async"/>
widths
Section titled widths
Added in:
astro@3.3.0
A list of widths to generate for the image.
If provided, this value will be used to generate a srcset
attribute on the <img>
tag. A sizes
property must also be provided.
Do not provide a value for densities
when using this value. Only one of these two values can be used to generate a srcset
.
Widths that are larger than the original image will be ignored to avoid upscaling the image.
---import { Image } from 'astro:assets';import myImage from '../assets/my_image.png'; // Image is 1600x900---<Image src={myImage} widths={[240, 540, 720, myImage.width]} sizes={`(max-width: 360px) 240px, (max-width: 720px) 540px, (max-width: 1600px) 720px, ${myImage.width}px`} alt="A description of my image."/>
<!-- Output --><img src="/_astro/my_image.hash.webp" srcset=" /_astro/my_image.hash.webp 240w, /_astro/my_image.hash.webp 540w, /_astro/my_image.hash.webp 720w, /_astro/my_image.hash.webp 1600w " sizes=" (max-width: 360px) 240px, (max-width: 720px) 540px, (max-width: 1600px) 720px, 1600px " alt="A description of my image." width="1600" height="900" loading="lazy" decoding="async"/>
format
Section titled formatYou can optionally state the image file type output to be used.
By default, the <Image />
component will produce a .webp
file.
quality
Section titled qualityquality
is an optional property that can either be:
- a preset (
low
,mid
,high
,max
) that is automatically normalized between formats. - a number from
0
to100
(interpreted differently between formats).
inferSize
Section titled inferSize
Added in:
astro@4.4.0
Allows you to set the original width
and height
of a remote image automatically.
By default, this value is set to false
and you must manually specify both dimensions for your remote image.
Add inferSize
to the <Image />
component (or inferSize: true
to getImage()
) to infer these values from the image content when fetched. This is helpful if you don’t know the dimensions of the remote image, or if they might change:
---import { Image } from 'astro:assets';---<Image src="https://example.com/cat.png" inferSize alt="A cat sleeping in the sun." />
inferSize
can fetch the dimensions of a remote image from a domain that has not been authorized, however the image itself will remain unprocessed.
Additional properties
Section titled Additional propertiesIn addition to the properties above, the <Image />
component accepts all properties accepted by the HTML <img>
tag.
For example, you can provide a class
to the final <img>
element.
---import { Image } from 'astro:assets';import myImage from '../assets/my_image.png';---
<!-- `alt` is mandatory on the Image component --><Image src={myImage} alt="" class="my-class" />
<!-- Output --><img src="/_astro/my_image.hash.webp" width="1600" height="900" decoding="async" loading="lazy" class="my-class" alt=""/>
Setting Default Values
Section titled Setting Default ValuesCurrently, there is no way to specify default values for all <Image />
components. Required attributes should be set on each individual component.
As an alternative, you can wrap these components in another Astro component for reuse. For example, you could create a component for your blog post images:
---import { Image } from 'astro:assets';
const { src, ...attrs } = Astro.props;---<Image src={src} {...attrs} />
<style> img :global(img), svg { margin-block: 2.5rem; border-radius: 0.75rem; }</style>
<Picture />
Section titled <Picture />
Added in:
astro@3.3.0
Use the built-in <Picture />
Astro component to display a responsive image with multiple formats and/or sizes.
---import { Picture } from 'astro:assets';import myImage from '../assets/my_image.png'; // Image is 1600x900---
<!-- `alt` is mandatory on the Picture component --><Picture src={myImage} formats={['avif', 'webp']} alt="A description of my image." />
<!-- Output --><picture> <source srcset="/_astro/my_image.hash.avif" type="image/avif" /> <source srcset="/_astro/my_image.hash.webp" type="image/webp" /> <img src="/_astro/my_image.hash.png" width="1600" height="900" decoding="async" loading="lazy" alt="A description of my image." /></picture>
Properties
Section titled Properties<Picture />
accepts all the properties of the <Image />
component, plus the following:
formats
Section titled formatsAn array of image formats to use for the <source>
tags. Entries will be added as <source>
elements in the order they are listed, and this order determines which format is displayed. For the best performance, list the most modern format first (e.g. webp
or avif
). By default, this is set to ['webp']
.
fallbackFormat
Section titled fallbackFormatFormat to use as a fallback value for the <img>
tag.
Defaults to .png
for static images (or .jpg
if the image is a JPG), .gif
for animated images, and .svg
for SVG files.
pictureAttributes
Section titled pictureAttributesAn object of attributes to be added to the <picture>
tag.
Use this property to apply attributes to the outer <picture>
element itself. Attributes applied to the <Picture />
component directly will apply to the inner <img>
element, except for those used for image transformation.
---import { Picture } from "astro:assets";import myImage from "../my_image.png"; // Image is 1600x900---
<Picture src={myImage} alt="A description of my image." pictureAttributes={{ style: "background-color: red;" }}/>
<!-- Output --><picture style="background-color: red;"> <source srcset="/_astro/my_image.hash.webp" type="image/webp" /> <img src="/_astro/my_image.hash.png" alt="A description of my image." width="1600" height="900" loading="lazy" decoding="async" /></picture>
The Astro template syntax also supports writing an <img>
tag directly, with full control over its final output. These images will not be processed and optimized.
It accepts all HTML <img>
tag properties, and the only required property is src
.
Local images in src/
Section titled Local images in src/Local images must be imported from the relative path from the existing .astro
file, or configure and use an import alias. Then, you can access the image’s src
and other properties to use in the <img>
tag.
For example, use the image’s own height
and width
properties to avoid CLS and improve Core Web Vitals.
---// import local imagesimport myDog from '../../images/pets/local-dog.jpg';---// access the image properties<img src={myDog.src} width={myDog.width} height={myDog.height} alt="A barking dog." />
Imported image assets match the following signature:
interface ImageMetadata { src: string; width: number; height: number; format: string;}
Images in public/
Section titled Images in public/For images located within public/
use the image’s file path relative to the public folder as the src
value:
<img src="/images/public-cat.jpg" alt="A sleeping cat." >
Remote images
Section titled Remote imagesFor remote images, use the image’s full URL as the src
value:
<img src="https://example.com/remote-cat.jpg" alt="A sleeping cat." >
Choosing <Image />
vs <img>
Section titled Choosing <Image /> vs <img>The <Image />
component optimizes your image and infers width and height (of local images) based on the original aspect ratio to avoid CLS.
Use the HTML <img>
element when you cannot use the <Image />
component, for example:
- for unsupported image formats
- when you do not want your image optimized by Astro
- to access and change the
src
attribute dynamically client-side
Authorizing remote images
Section titled Authorizing remote imagesYou can configure lists of authorized image source URL domains and patterns for image optimization using image.domains
and image.remotePatterns
. This configuration is an extra layer of safety to protect your site when showing images from an external source.
Remote images from other sources will not be optimized, but using the <Image />
component for these images will prevent Cumulative Layout Shift (CLS).
For example, the following configuration will only allow remote images from astro.build
to be optimized:
export default defineConfig({ image: { domains: ["astro.build"], }});
The following configuration will only allow remote images from HTTPS hosts:
export default defineConfig({ image: { remotePatterns: [{ protocol: "https" }], }});
Using Images from a CMS or CDN
Section titled Using Images from a CMS or CDNImage CDNs work with all Astro image options. Use an image’s full URL as the src
attribute in the <Image />
component, an <img>
tag, or in Markdown notation. For image optimization with remote images, also configure your authorized domains or URL patterns.
Alternatively, if the CDN provides a Node.js SDK, you can use that in your project. For example, Cloudinary’s SDK can generate an <img>
tag with the appropriate src
for you.
Images in Markdown files
Section titled Images in Markdown filesUse standard Markdown ![alt](src)
syntax in your .md
files. This syntax works with Astro’s Image Service API to optimize your local images stored in src/
. Remote images and images stored in the public/
folder are not optimized.
# My Markdown Page
<!-- Local image stored in src/assets/ --><!-- Use a relative file path or import alias -->![A starry night sky.](../assets/stars.png)
<!-- Image stored in public/images/ --><!-- Use the file path relative to public/ -->![A starry night sky.](/images/stars.png)
<!-- Remote image on another server --><!-- Use the full URL of the image -->![Astro](https://example.com/images/remote-image.png)
The <img>
tag is not supported for local images, and the <Image />
component is unavailable in .md
files.
If you require more control over your image attributes, we recommend using the .mdx
file format, which allows you to include Astro’s <Image />
component or a JSX <img />
tag in addition to the Markdown syntax. Use the MDX integration to add support for MDX to Astro.
Images in MDX files
Section titled Images in MDX filesYou can use Astro’s <Image />
component and JSX <img />
tags in your .mdx
files by importing both the component and your image. Use them just as they are used in .astro
files.
Additionally, there is support for standard Markdown ![alt](src)
syntax with no import required.
---title: My Page title---import { Image } from 'astro:assets';import rocket from '../assets/rocket.png';
# My MDX Page
// Local image stored in the the same folder![Houston in the wild](houston.png)
// Local image stored in src/assets/<Image src={rocket} alt="A rocketship in space." /><img src={rocket.src} alt="A rocketship in space." />![A rocketship in space](../assets/rocket.png)
// Image stored in public/images/<Image src="/images/stars.png" alt="A starry night sky." /><img src="/images/stars.png" alt="A starry night sky." />![A starry night sky.](/images/stars.png)
// Remote image on another server<Image src="https://example.com/images/remote-image.png" /><img src="https://example.com/images/remote-image.png" />![Astro](https://example.com/images/remote-image.png)
Images in content collections
Section titled Images in content collectionsImages in content collections will be processed the same way they are in Markdown and MDX depending on which file type you are using.
Additionally, you can declare an associated image for a content collections entry, such as a blog post’s cover image, in your frontmatter using its path relative to the current folder:
---title: "My first blog post"cover: "./firstpostcover.jpeg" # will resolve to "src/content/blog/firstblogcover.jpeg"coverAlt: "A photograph of a sunset behind a mountain range."---
This is a blog post
The image
helper for the content collections schema lets you validate the image metadata using Zod.
import { defineCollection, z } from "astro:content";
const blogCollection = defineCollection({ schema: ({ image }) => z.object({ title: z.string(), cover: image().refine((img) => img.width >= 1080, { message: "Cover image must be at least 1080 pixels wide!", }), coverAlt: z.string(), }),});
export const collections = { blog: blogCollection,};
The image will be imported and transformed into metadata, allowing you to pass it as a src
to <Image/>
, <img>
, or getImage()
.
The example below shows a blog index page that renders the cover photo and title of each blog post from the schema above:
---import { Image } from "astro:assets";import { getCollection } from "astro:content";const allBlogPosts = await getCollection("blog");---
{ allBlogPosts.map((post) => ( <div> <Image src={post.data.cover} alt={post.data.coverAlt} /> <h2> <a href={"/blog/" + post.slug}>{post.data.title}</a> </h2> </div> ))}
Images in UI framework components
Section titled Images in UI framework componentsWhen adding images in a UI framework component, use the framework’s own image syntax to render an image (e.g. <img />
in JSX, <img>
in Svelte).
Local images must first be imported to access their image properties such as src
.
import stars from "../assets/stars.png";
export default function ReactImage() { return ( <img src={stars.src} alt="A starry night sky." /> )}
<script> import stars from '../assets/stars.png';</script>
<img src={stars.src} alt="A starry night sky." />
Passing the Image component
Section titled Passing the Image componentThe <Image />
component, like any other Astro component, is unavailable to UI framework components.
But, you can pass the static content generated by <Image />
to a framework component inside a .astro
file as children or using a named <slot/>
:
---import ReactComponent from './ReactComponent.jsx';import { Image } from 'astro:assets';import stars from '~/stars/docline.png';---
<ReactComponent> <Image src={stars} alt="A starry night sky." /></ReactComponent>
Generating images with getImage()
Section titled Generating images with getImage()getImage()
relies on server-only APIs and breaks the build when used on the client.
The getImage()
function is intended for generating images destined to be used somewhere else than directly in HTML, for example in an API Route. It also allows you to create your own custom <Image />
component.
![](/houston_chef.webp)
getImage()
takes an options object with the same properties as the Image component (except alt
).
---import { getImage } from "astro:assets";import myBackground from "../background.png";
const optimizedBackground = await getImage({src: myBackground, format: 'webp'});---
<div style={`background-image: url(${optimizedBackground.src});`}></div>
It returns an object with the following properties:
{ rawOptions: {...}, // Original parameters passed options: {...}, // Validated parameters passed src: "...", // Path to the generated image srcSet: { values: [...], // Generated values for srcset, every entry has a url and a size descriptor attribute: "", // Generated srcset attribute from the values } attributes: {...} // Additional HTML attributes needed to render the image (width, height, style, etc..)}
Alt Text
Section titled Alt TextNot all users can see images in the same way, so accessibility is an especially important concern when using images. Use the alt
attribute to provide descriptive alt text for images.
This attribute is required for both the <Image />
and <Picture />
components. If no alt text is provided, a helpful error message will be provided reminding you to include the alt
attribute.
If the image is merely decorative (i.e. doesn’t contribute to the understanding of the page), set alt=""
so that screen readers know to ignore the image.
Default image service
Section titled Default image serviceSharp is the default image service used for astro:assets
. You can further configure the image service using the image.service
option.
When using a strict package manager like pnpm
, you may need to manually install Sharp into your project even though it is an Astro dependency:
pnpm add sharp
Configure Squoosh
Section titled Configure SquooshIf you would prefer to use Squoosh to transform your images, update your config with the following:
import { defineConfig, squooshImageService } from 'astro/config';
export default defineConfig({ image: { service: squooshImageService(), },});
Configure no-op passthrough service
Section titled Configure no-op passthrough serviceIf your adapter for server
or hybrid
mode does not support Astro’s built-in Squoosh and Sharp image optimization (e.g. Deno, Cloudflare), you can configure a no-op image service to allow you to use the <Image />
and <Picture />
components. Note that Astro does not perform any image transformation and processing in these environments. However, you can still enjoy the other benefits of using astro:assets
, including no Cumulative Layout Shift (CLS), the enforced alt
attribute, and a consistent authoring experience.
Configure the passthroughImageService()
to avoid both Squoosh and Sharp image processing:
import { defineConfig, passthroughImageService } from 'astro/config';
export default defineConfig({ image: { service: passthroughImageService() }});
Community Integrations
Section titled Community IntegrationsThere are several third-party community image integrations for optimizing and working with images in your Astro project.
Learn