#explain image densities
20 messages · Page 1 of 1 (latest)
Hi @maiden field. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
Image Densities in Astro
The densities prop on the <Image /> component allows you to generate multiple versions of an image for different pixel densities (e.g., for high-DPI/Retina displays). [densities prop]
How it works
When you provide a densities array, Astro uses those values to generate a srcset attribute with x descriptors, so the browser can pick the best image version based on the device's screen density.
Example with [1.5, 2]
---
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."
/>
This produces:
<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"
/>
So if you define [1, 2], Astro would generate two image variants — one for 1x (standard displays) and one for 2x (Retina/high-DPI displays) — and include them in the srcset. [densities prop]
Important constraints
- Do not use
densitiestogether withwidths— only one can be used at a time to generate asrcset, since they produce different descriptor types (xvsw). [incompatible options] densitiesis incompatible with thelayoutprop (orimage.layoutconfig) — it will be ignored if a layout is set. [densities prop]- Densities that would result in sizes larger than the original image are ignored to prevent upscaling. [densities prop]
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@maiden field Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@small loom why is the width set to 1/2 in the example?
Let me check the knowledge base for you again. One moment! :books:
The knowledge sources don't explicitly explain why myImage.width / 2 is used in that example, but the reasoning can be inferred from how densities work:
When you specify densities={[1.5, 2]}, you're telling the browser that the provided image variants are for 1.5x and 2x displays. The width prop defines the base (1x) display size of the image. [densities prop]
So if the original image is 1600px wide, setting width={myImage.width / 2} (i.e., 800px) means:
- The image is intended to display at 800px on a standard 1x screen.
- At
1.5xdensity, the browser will use a version that is800 × 1.5 = 1200pxwide. - At
2xdensity, the browser will use a version that is800 × 2 = 1600pxwide — which matches the original image's full resolution.
This way, the original 1600px image is used efficiently as the high-density variant, without needing to upscale. Densities that would result in sizes larger than the original image are ignored to prevent upscaling. [densities prop]
In short, halving the width is a deliberate choice to make the original image serve as the 2x variant, keeping everything within the bounds of the source image's actual dimensions.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@maiden field Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@small loom can i choose NOT to optimize an <Image/> element? or should i just use a plain img tag?
Let me check the knowledge base for you again. One moment! :books:
Yes, you have both options available:
Using <Image /> without optimization
You can still use the <Image /> component for images that won't be optimized — specifically images in the public/ folder or remote images that are not in your authorized domains list. In these cases, the component behaves like a plain <img> tag (no processing), but you still get benefits like CLS prevention: [Astro components]
"The resulting image will be the same as using the HTML
<img>. However, using the image component for all images provides a consistent authoring experience and prevents Cumulative Layout Shift (CLS) even for your unoptimized images."
Using a plain <img> tag
You can also use a native HTML <img> tag directly in .astro files. Images rendered this way will not be processed, optimized, or transformed — they are copied into the build as-is. [unprocessed images]
The docs recommend using <img> when:
- The image format is unsupported
- You don't want Astro to optimize the image
- You need to dynamically change the
srcattribute client-side
Recommendation
Prefer <Image /> even for unoptimized images, since it still prevents CLS by enforcing width and height. Only fall back to <img> when you have a specific reason to need full control over the raw output. [choosing Image vs img]
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@maiden field Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@small loom you failed to tell me how, you tin can.
how do i choose not to optimize with <Image/> ?
Let me check the knowledge base for you again. One moment! :books:
Fair point — let me be more concrete.
To use <Image /> without optimization, simply point it at an image in your public/ folder or a remote URL that is not in your authorized domains list. Astro cannot process these, so no optimization occurs, but you still get CLS protection. [Astro components]
---
import { Image } from 'astro:assets';
---
<!-- public/ image — not optimized -->
<Image
src="/images/my-public-image.png"
alt="descriptive text"
width="200"
height="150"
/>
<!-- Remote image outside authorized domains — not optimized -->
<Image
src="<https://example.com/remote-image.jpg">
alt="descriptive text"
width="200"
height="150"
/>
Alternatively, if you want to globally disable image processing, you can configure the passthrough image service in astro.config.mjs, which disables optimization for all images: [passthrough service]
import { defineConfig, passthroughImageService } from 'astro/config';
export default defineConfig({
image: {
service: passthroughImageService()
}
});
The knowledge sources don't describe a per-image prop on <Image /> to explicitly opt out of optimization for local src/ images — for that use case, a plain <img> tag is the recommended approach. [choosing Image vs img]
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@maiden field Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@small loom well the image i want to NOT optimize is in a remote URL, and that URL is in my domains list. I just want to not optimize it.
Let me check the knowledge base for you again. One moment! :books:
That's a tricky situation. The knowledge sources don't describe a way to opt out of optimization for a specific <Image /> component when the image's remote URL is already in your authorized domains list.
Your practical options based on what the docs do say:
-
Use a plain
<img>tag — this bypasses all Astro processing entirely, regardless of whether the domain is authorized: [unprocessed images]<img src="<https://example.com/remote-image.jpg"> alt="A description." /> -
Remove the domain from your authorized list — if you remove it from
image.domainsorimage.remotePatterns, Astro will no longer optimize images from that source. You could then use<Image />and it will pass through unoptimized. However, this would affect all images from that domain, not just one. [authorizing remote images]