Picture

Create responsive images using the Transform Images plugin

Options

name string

The key name for the transformations definitions

Default:
"transformImages"
order string[]

The priority order of the formats

Default:
[ "avif", "webp", "png", "jpg" ]

Description

The Picture plugin creates <picture> elements, adding all <source> as needed or generates the srcset property to provide versions in different formats and resolutions for the same image. It uses the transform_images plugin under the hood to make the transformations.

Installation

Import this plugin in your _config.ts file to use it and make sure to register it exactly above transform_images:

import lume from "lume/mod.ts";
import picture from "lume/plugins/picture.ts";
import transformImages from "lume/plugins/transform_images.ts";

const site = lume();

site.use(picture(/* Options */));
site.use(transformImages());

export default site;

Example

Create an <img> element with the transform-images attribute containing all the desired formats and sizes for the image:

<img src="/flowers.jpg" transform-images="avif webp jpg 300@2" />

The transform-images attribute of this image contains the formats (avif, webp, jpg) and the different sizes (300 which means 300 pixels). The @2 suffix indicates that this size should support also the 2x resolution. The output HTML code is:

<picture>
  <source
    srcset="/flowers-300w.avif, /flowers-300w@2.avif 2x"
    type="image/avif"
  />
  <source
    srcset="/flowers-300w.webp, /flowers-300w@2.webp 2x"
    type="image/webp"
  />
  <img src="/flowers-300w.jpg" srcset="/flowers-300w@2.jpg 2x" />
</picture>

The plugin not only generates the HTML code but also sends the configuration to the transform_images plugin to generate all these images.

Sizes

It's possible to create different sizes. Keep in mind that it requires the sizes attribute:

<img
  sizes="(min-width: 640px) 18rem, 11rem"
  src="/flowers.jpg"
  transform-images="avif webp jpg 640 1080"
>
<picture>
  <source
    srcset="/flowers-640w.avif 640w, /flowers-1080w.avif 1080w"
    type="image/avif"
    sizes="(min-width: 640px) 18rem, 11rem"
  >
  <source
    srcset="/flowers-640w.webp 640w, /flowers-1080w.webp 1080w"
    type="image/webp"
    sizes="(min-width: 640px) 18rem, 11rem"
  >
  <img
    sizes="(min-width: 640px) 18rem, 11rem"
    src="/flowers-640w.jpg"
    srcset="/flowers-1080w.jpg 1080w"
  >
</picture>

Responsive images

You can set the transform-images attribute to different sources inside a picture to generate responsive images:

<picture>
  <!-- version for small devices -->
  <source
    srcset="/flowers-detail.jpg"
    media="(min-width: 600px)"
    transform-images="avif webp jpg 1000@2"
  >

  <!-- version for big screens -->
  <source srcset="/flowers-big.jpg" transform-images="avif webp jpg 1000@2">

  <!-- default image -->
  <img src="/flowers-mini.jpg" transform-images="300@2">
</picture>

The plugin generates the following code:

<picture>
  <!-- version for small devices -->
  <source
    srcset="/flowers-1000w.avif, /flowers-1000w@2.avif 2x"
    type="image/avif"
    media="(min-width: 600px)"
  >
  <source
    srcset="/flowers-1000w.webp, /flowers-1000w@2.webp 2x"
    type="image/webp"
    media="(min-width: 600px)"
  >
  <source
    srcset="/flowers-1000w.jpg, /flowers-1000w@2.jpg 2x"
    media="(min-width: 600px)"
  >

  <!-- version for big screens -->
  <source
    srcset="/flowers-1000w.avif, /flowers-1000w@2.avif 2x"
    type="image/avif"
  >
  <source
    srcset="/flowers-1000w.webp, /flowers-1000w@2.webp 2x"
    type="image/webp"
  >
  <source srcset="/flowers-1000w.jpg, /flowers-1000w@2.jpg 2x">

  <!-- default image -->
  <img src="/flowers-300w.jpg" srcset="/flowers-300w@2.jpg 2x">
</picture>

Configuring the img container

If the transform-images attribute is assigned to a HTML element that is not an image, the plugin will search for all img elements found inside that element. This is useful if you don't want to include this attribute in every <img> element, because you want to avoid repetition if all images have the same configuration, or the HTML content is generated from markdown content that you want to keep clean.

<div transform-images="avif webp jpg 300@2">
  <!-- All images inside will be transformed -->
  <img src="/flowers.jpg" />

  <!-- You can override the value for a specific image -->
  <img src="/flowers.jpg" transform-images="avif jpg 600" />

  <!-- This one is not tranformed because the value is empty -->
  <img src="/flowers.jpg" transform-images="" />
</div>