#image support

9 messages · Page 1 of 1 (latest)

tepid solstice
#

which image formats does astro's Image support? how about gif or animated webp?

lucid mossBOT
#

Hi @tepid solstice. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Astro’s image support is defined in two places:

  1. Input formats (what you can import / process):
    The ImageInputFormat type lists the formats Astro’s image services accept:

These are the formats you can use with import and then pass to <Image /> / <Picture /> / getImage().

  1. Output formats (what <Image /> / <Picture /> can generate):
    The ImageOutputFormat type (used by the format prop on <Image /> and formats / fallbackFormat on <Picture />) includes:

By default, <Image /> outputs WebP unless you override format. [format prop]

GIF and animated WebP

The docs explicitly warn that not all formats are supported by the built‑in optimization services, and give GIF as an example of a format that may not be optimizable. In that case, you should use a plain <img> tag instead of <Image /> / <Picture />:

---
// local GIF import
import rocket from '../assets/images/rocket.gif';
---
<img src={rocket.src} width={rocket.width} height={rocket.height} alt="A rocketship in space." />

[Unsupported image format]

#

The knowledge sources do not explicitly state whether animated WebP is preserved or supported when using <Image /> / <Picture />. They only describe WebP as a supported input/output format, without mentioning animation. [ImageInputFormat; ImageOutputFormat]

So, based on the docs:

  • Static formats listed in ImageInputFormat are supported as inputs.
  • <Image /> / <Picture /> can output the formats listed in ImageOutputFormat, defaulting to WebP.
  • For GIFs (and likely other animated formats), you may need to fall back to a regular <img> tag instead of relying on Astro’s optimization. [Unsupported image format]
  • The behavior for animated WebP is not clearly documented in the provided sources.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@tepid solstice Kapa.ai is still learning and improving, please let me know how I did by reacting below.

tepid solstice
#

@lucid moss I want to support using gifs in my astro content collection. It should be opaque if it is a gif or a support format. how to implement this

lucid mossBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

The knowledge sources don’t describe a built‑in way for content collections to automatically switch between <Image /> and <img> based on whether a file is a GIF vs. an optimizable format. They do, however, show:

  • How images in content collections become ImageMetadata you can pass to <Image /> / <img>. [Images in collections]
  • That GIFs may not be supported by the image optimizer and should be rendered with <img>. [Unsupported image format]

Given that, you can make this “opaque” to your content by:

  1. Use image() in your collection schema so all images (including GIFs) become ImageMetadata:
// src/content.config.ts
import { defineCollection } from "astro:content";
import { z } from "astro/zod";

const blog = defineCollection({
  schema: ({ image }) =>
    z.object({
      title: z.string(),
      cover: image(),      // can be jpg/png/webp/gif/etc.
      coverAlt: z.string(),
    }),
});

export const collections = { blog };

[Images in collections]

  1. Create a small wrapper component that decides at render time whether to use <Image /> or <img> based on src.format. The docs show that imported images expose format on ImageMetadata. [Display unprocessed images]
---
// src/components/ContentImage.astro
import type { ImageMetadata } from 'astro';
import { Image } from 'astro:assets';

interface Props {
  src: ImageMetadata;
  alt: string;
}

const { src, alt } = Astro.props;
const isGif = src.format === 'gif';
---
#

{isGif ? (
// Unoptimized GIF
<img src={src.src} width={src.width} height={src.height} alt={alt} />
) : (
// Optimized for supported formats
<Image src={src} alt={alt} />
)}


This uses only documented properties of `ImageMetadata` (`src`, `width`, `height`, `format`) and the recommended `<img>` fallback for GIFs. [[Display unprocessed images](<https://docs.astro.build/en/guides/images/#images-in-src>); [Unsupported image format](<https://docs.astro.build/en/reference/errors/unsupported-image-format/#what-went-wrong>)]

3. **Use the wrapper in your collection pages**, keeping content opaque to the actual format:

```astro
---
// src/pages/blog.astro
import { getCollection } from "astro:content";
import ContentImage from "../components/ContentImage.astro";

const posts = await getCollection("blog");
---

{posts.map((post) => (
  <article>
    <ContentImage src={post.data.cover} alt={post.data.coverAlt} />
    <h2><a href={`/blog/${post.slug}`}>{post.data.title}</a></h2>
  </article>
))}

From the content author’s perspective, they just set cover: "./image.whatever"; your wrapper hides whether it’s a GIF (rendered via <img>) or a supported format (rendered via <Image />).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: