@unpic/astro

ascorbic/unpic-img

A high-performance, responsive image component for Astro. Automatically supports most image CDNs and CMSs with no build step needed.

Installation and usage

npm install @unpic/astro

Image component

In almost all cases you can just use the Image component, which will generate an optimized, responsive image for you with automatic format detection.

---
import { Image } from "@unpic/astro";
---

<Image
  src="https://cdn.shopify.com/static/sample-images/bath_grande_crop_center.jpeg"
  layout="constrained"
  width={800}
  height={600}
  alt="A lovely bath"
/>

Source component

If you need to do art direction, or handle different formats in a CDN that doesn’t do auto-detection then you will need a <picture> element. You can use the Source component to generate the correct <source> elements for you. The usage depends on what you are trying to do.

Art direction

Art direction is where you want to use different images at different screen sizes. For example, you might want to use a portrait image on mobile and a landscape image on desktop. You can do this with a <picture> tag and the Source component.

First use a normal <picture> tag, and then add a Source component for each image you want to use. The Source component will generate a <source> tag with the correct srcset and sizes attributes for you.

Each Source component takes a media prop, which is a media query that will be used to determine if the image should be used. The first Source component with a matching media query will be used, and the rest will be ignored. It also takes src, width, height and layout props, which are the same as the Image component. This means you can either use the same image with a different crop or layout, or a completely different image.

You need to include an <Image> as the final element in the <picture> tag. This is used as a fallback for browsers that don’t support <picture>, or if none of the media queries match. In a <picture> tag, any styling must be applied to the <img> tag, and are applied whichever <source> is used. <source> tags themselves cannot be styled. When using art direction you must set the unstyled prop on the <Image> element, because otherwise the image will have the same styling at all screen widths. Instead you need to use CSS media queries to style the <img> tag.

---
import { Source } from "@unpic/astro";
---

<picture class="hero">
  <!-- Large screens get a full-width hero image -->
  <Source
    src="https://images.unsplash.com/photo-1694406805270-f3a93e91f4b6"
    media="(min-width: 601px)"
    layout="fullWidth"
  />
  <!-- Small screens get a constrained square image -->
  <Source
    src="https://images.unsplash.com/photo-1693711942336-f4f9963bd364"
    media="(max-width: 600px)"
    width={600}
    height={600}
  />
  <!-- Always include an Image as the final element -->
  <Image
    src="https://images.unsplash.com/photo-1693711942336-f4f9963bd364"
    width={600}
    height={600}
    alt="Aurora"
    unstyled
  />
</picture>

<style>
  /* Style for all layouts */
  .hero img {
    object-fit: cover;
    width: 100%;
  }

  @media (min-width: 601px) {
    /* Style for full-width layout */
    .hero img {
      height: 600px;
    }
  }
  @media (max-width: 600px) {
    /* Style for constrained layout */
    .hero img {
      max-width: 600px;
      /* Set the image aspect-ratio */
      aspect-ratio: 1/1;
    }
  }
</style>

Image Props

The component accepts all the props of an <img> tag, plus the following:

layout

The resizing behaviour of the image.

  • constrained: (default) the image will be rendered at a maximum of width and height, but will scale down automatically if the container is smaller, maintaining the aspect ratio.
  • fullWidth: the image will be rendered at full width of its container. This is optimized for full-width hero images. You can set height to a fixed value, which will mean the image will be rendered at that fixed height and scale horizontally to fill the container.
  • fixed: the image will be rendered at the exact size specified by width and height

priority

By default, images are loaded lazily. If priority is set to true, the image will be loaded eagerly, and will be given high priority by the browser. This is useful for images that are above the fold, particularly large ones such as hero images.

background

Either an image URL, CSS gradient or CSS colour value. If set to auto, a low-resolution version of the image will be rendered as a background image, with a blurred placeholder effect. This is still loaded from the remote server, so if you can instead provide an inline base64-encoded version of the image or background colour, you should do that instead. Look at @unpic/placeholder for a library that can generate these placeholders.

Bear in mind that this is not removed after the image loads, so it will be visible if the image has transparency.

aspectRatio

Instead of specifying both width and height, you can specify can aspectRatio.

cdn

By default the CDN is auto-detected from the src URL. If you want to override this, you can specify a CDN object. See the unpic for supported values.

breakpoints

By default the image breakpoints used in the srcset are generated based on the layout and image size. You can override this by specifying an array of breakpoints. The breakpoints are specified as an array of numbers, representing the width of the image in pixels.

Other props

Any prop supported by <img> tags can be passed in, except srcset which is generated from src. The following props are set automatically, but can be overridden if you need to:

  • sizes
  • role
  • decoding
  • loading
  • fetchpriority

Source Props

The Source component must be wrapped in a <picture> tag, and accepts the following props:

media

A media query string. If this matches, the source will be used. Normally this would be something like (min-width: 768px), but it can also be used for dark mode detection, e.g. (prefers-color-scheme: dark) or other media queries.

type

The MIME type of the image. This is used to generate the type attribute of the <source> tag, but is also passed to the CDN to generate the correct image type. Normally an image CDN will auto-detect the required image format, but not all support it and in that case you can use this component with type to specify multiple image format options and the browser will choose the best supported one.

Other props

It also accepts the following props that are used in the same way as in the Image component:

  • layout
  • src
  • width
  • height
  • aspectRatio
  • cdn
  • breakpoints