Skip to content

Responsive images #1042

@ascorbic

Description

@ascorbic

Summary

The current Astro image component offers a lot of flexibility for displaying images. It supports densities and widths props to help generate the correct img attributes, and the default image service supports modern formats such as AVIF and WebP. While this gives users the tools to create performant and responsive images, it does not give guidance in how to use them - and requires that they are set on all images. This proposal is for a more opinionated image component. It would offer all of the tools from the current component, and also introduce new props and config options that follow best practices by default.

Background & Motivation

Displaying images on the web is difficult, even for the most experienced developers. Users suffer slower page loads, and poor experience as the page layout jumps around. Meanwhile sites experience poor core web vitals scores for performance, cumulative layout shift (CLS) and largest contentful paint (LCP).

The most common imgtag attributes are well known: src, alt, width and height, there are several lesser-known attributes that are needed if an image is to have the best performance. All of these are optional according to the spec, but best practices require most of them. The most important are srcset, sizes, loading, decoding and fetchpriority.

These are a lot of attributes to remember and understand, though the final three have values that are usually safe to think of as dependent on just whether the image is onscreen when the page loads. Astro Image already sets loading and decoding to lazy and async by default. However srcset and sizes have no simple rules because they depend on how the image will be displayed, and can be very hard to do correctly. Images also need to be styled correctly if they are to be responsive and avoid CLS.

This proposal is inspired by the attributes generated by @unpic/astro, which I created, but with some changes to make it closer to the existing component behavior, and less focussed on image CDNs.

Goals

  • A single layout prop that, when combined with existing props, sets the attributes that will make an image responsive and following best practices.
  • Config options to change the defaults for all images
  • Backwards-compatible, so that existing images are unaffected unless they set the props or config options.
  • Add support for optional cropping in image services

Non-goals

  • Placeholder support
  • Automatic provider detection
  • Art direction
  • Implementing crop support for all existing image services

Example

Responsive images will be enabled by setting the layout prop to responsive, fixed or full-width.

---
import { Image } from "astro:assets"
import rocket from "./rocket.jpg"
---
<Image src={rocket} width={800} height={600} layout="responsive" />

A new layout option for the image config will default all images to that layout. This can be overridden on each image.

import { defineConfig } from 'astro/config';

export default defineConfig({
  image: {
    layout: "responsive",
  },
});

References

These served as inspiration, and/or are useful for understanding best practices:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    Stage 3: Accepted Proposals, Has RFC

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions