Asian Americans Advancing Justice — Stand Against Hatred
Eleventy
The possum is Eleventy’s mascot
Eleventy Documentation
WARNING:
This is an older version of Eleventy. Go to the newest Eleventy docs (current path: /docs/plugins/image/) or the full release history.
Menu
Eleventy 1.93s
Astro 22.90s

Image

Contents

Low level utility to perform build-time image transformations for both vector and raster images. Output multiple sizes, save multiple formats, cache remote images locally. Uses the sharp image processor.

You maintain full control of the HTML. Use with <picture> or <img> or CSS background-image, or others! Works great to add width and height to your images!

Installation Jump to heading

npm install @11ty/eleventy-img

Usage Jump to heading

This utility returns a Promise and works best in async friendly functions, filters, shortcodes. It can also work in synchronous environments (Synchronous Usage).

Filename .eleventy.js
const Image = require("@11ty/eleventy-img");

(async () => {
let url = "https://images.unsplash.com/photo-1608178398319-48f814d0750c";
let stats = await Image(url, {
widths: [300]
});

console.log( stats );
})();

Three things happen here:

  1. If the first argument is a full URL (not a local file path), we download the remote image and cache it locally using the Fetch plugin. This cached original is then used for the cache duration to avoid a bunch of network requests.
  2. From that cached full-size original, images are created for each format and width, in this case: ./img/6dfd7ac6-300.webp and ./img/6dfd7ac6-300.jpeg.
  3. The metadata object is populated and returned, describing those new images:
{
webp: [
{
format: 'webp',
width: 300,
height: 300,
filename: '6dfd7ac6-300.webp',
outputPath: 'img/6dfd7ac6-300.webp',
url: '/img/6dfd7ac6-300.webp',
sourceType: 'image/webp',
srcset: '/img/6dfd7ac6-300.webp 300w',
size: 10184
}
],
jpeg: [
{
format: 'jpeg',
width: 300,
height: 300,
filename: '6dfd7ac6-300.jpeg',
outputPath: 'img/6dfd7ac6-300.jpeg',
url: '/img/6dfd7ac6-300.jpeg',
sourceType: 'image/jpeg',
srcset: '/img/6dfd7ac6-300.jpeg 300w',
size: 15616
}
]
}

Here’s the output images, one webp and one jpeg:

the webp output created by this Image plugin (it’s a nebula) the jpeg output created by this Image plugin (it’s a nebula)

Output Widths Jump to heading

Controls how many output images will be created for each image format. Aspect ratio is preserved.

Output Formats Jump to heading

Use almost any combination of these:

Output Locations Jump to heading

URL Path Jump to heading

A path-prefix-esque directory for the <img src> attribute. e.g. /img/ for <img src="/img/MY_IMAGE.jpeg">:

Output Directory Jump to heading

Where to write the new images to disk. Project-relative path to the output image directory. Maybe you want to write these to your output directory directly (e.g. ./_site/img/)?

Caching Remote Images Locally Jump to heading

Added in Image 0.3.0 For any full URL first argument to this plugin, the full-size remote image will be downloaded and cached locally. See all relevant eleventy-fetch options.

{
cacheOptions: {
// if a remote image URL, this is the amount of time before it fetches a fresh copy
duration: "1d",

// project-relative path to the cache directory
directory: ".cache",

removeUrlQueryParams: false,
},
}

When caching remote images, you may want to check the processed image output into your git (et al) repository to avoid refetches in the future. If remote images are not checked in, they may be refetched every time on your CI server unless you preserve the .cache folder between builds.

Options for SVG Jump to heading

Skip raster formats for SVG Jump to heading

Added in Image 0.4.0 If using SVG output (the input format is SVG and svg is added to your formats array), we will skip all of the raster formats even if they’re in formats. This may be useful in a CMS-driven workflow when the input could be vector or raster.

Allow SVG to upscale Jump to heading

Added in Image 0.4.0 While we do prevent raster images from upscaling (and filter upscaling widths from the output), you can optionally enable SVG input to upscale to larger sizes when converting to raster format.

Custom Filenames Jump to heading

Added in Image 0.4.0 Don’t like those hash ids? Make your own!

{
// Define custom filenames for generated images
filenameFormat: function (id, src, width, format, options) {
// id: hash of the original image
// src: original image path
// width: current width in px
// format: current file format
// options: set of options passed to the Image call

return `${id}-${width}.${format}`;
}
}
Custom Filename Example: Use the original file slug
const path = require("path");
const Image = require("@11ty/eleventy-img");

await Image("./test/bio-2017.jpg", {
widths: [300],
formats: ["auto"],
filenameFormat: function (id, src, width, format, options) {
const extension = path.extname(src);
const name = path.basename(src, extension);

return `${name}-${width}w.${format}`;
}
});

// Writes: "test/img/bio-2017-300w.jpeg"

Using a Hosted Image Service Jump to heading

Custom URLs Jump to heading

Added in Image 0.8.3 Want to use a hosted image service instead? You can override the entire URL. Takes precedence over filenameFormat option. Useful with statsSync or statsByDimensionsSync.

When you use this, returned data will not include filename or outputPath.

{
urlFormat: function ({
hash, // not included for `statsOnly` images
src,
width,
format,
}) {
return `https://sample-image-service.11ty.dev/${encodeURIComponent(src)}/${width}/${format}/`;
}
}

Stats Only Jump to heading

Added in Image 1.1.0 Skips all image processing to return metadata. Doesn’t read files, doesn’t write files. Use this as an alternative to the separate statsSync* functions—this will use in-memory cache and de-duplicate requests.

With remotely hosted images, you may also need to supply the dimensions when using statsOnly:

{
statsOnly: true,
remoteImageMetadata: {
width,
height,
format, // optional
}
}

Change the default Hash length Jump to heading

Added in v1.0.0 You can customize the length of the default filename format hash by using the hashLength property.

const Image = require("@11ty/eleventy-img");

await Image("./test/bio-2017.jpg", {
hashLength: 8 // careful, don’t make it _too_ short!
});

Use this in your templates Jump to heading

Asynchronous Shortcode Jump to heading

INFO:
The examples below require an async-friendly shortcodes (works in Nunjucks, Liquid, JavaScript, and WebC). Note that Nunjucks macros cannot use asynchronous shortcodes. If you use macros, use synchronous shortcodes described below.
Choose one: We generate the HTML Do it yourself: <img> Do it yourself: <picture>

Added in Image 0.7.2The generateHTML function is available in Eleventy Image v0.7.2 or higher.

Filename .eleventy.js
const Image = require("@11ty/eleventy-img");

// Only one module.exports per configuration file, please!
module.exports = function(eleventyConfig) {
eleventyConfig.addShortcode("image", async function(src, alt, sizes) {
let metadata = await Image(src, {
widths: [300, 600],
formats: ["avif", "jpeg"]
});

let imageAttributes = {
alt,
sizes,
loading: "lazy",
decoding: "async",
};

// You bet we throw an error on missing alt in `imageAttributes` (alt="" works okay)
return Image.generateHTML(metadata, imageAttributes);
});
};
Filename .eleventy.js
const Image = require("@11ty/eleventy-img");

// Only one module.exports per configuration file, please!
module.exports = function(eleventyConfig) {
eleventyConfig.addShortcode("image", async function(src, alt) {
if(alt === undefined) {
// You bet we throw an error on missing alt (alt="" works okay)
throw new Error(`Missing \`alt\` on myImage from: ${src}`);
}

let metadata = await Image(src, {
widths: [600],
formats: ["jpeg"]
});

let data = metadata.jpeg[metadata.jpeg.length - 1];
return `<img src="${data.url}" width="${data.width}" height="${data.height}" alt="${alt}" loading="lazy" decoding="async">`;
});
};
Filename .eleventy.js
const Image = require("@11ty/eleventy-img");

// Only one module.exports per configuration file, please!
module.exports = function(eleventyConfig) {
eleventyConfig.addShortcode("image", async function(src, alt, sizes = "100vw") {
if(alt === undefined) {
// You bet we throw an error on missing alt (alt="" works okay)
throw new Error(`Missing \`alt\` on responsiveimage from: ${src}`);
}

let metadata = await Image(src, {
widths: [300, 600],
formats: ['webp', 'jpeg']
});

let lowsrc = metadata.jpeg[0];
let highsrc = metadata.jpeg[metadata.jpeg.length - 1];

return `<picture>
${Object.values(metadata).map(imageFormat => {
return ` <source type="${imageFormat[0].sourceType}" srcset="${imageFormat.map(entry => entry.srcset).join(", ")}" sizes="${sizes}">`;
}).join("\n")}

<img
src="
${lowsrc.url}"
width="
${highsrc.width}"
height="
${highsrc.height}"
alt="
${alt}"
loading="lazy"
decoding="async">
</picture>
`
;
});
};

The addShortcode method is async-friendly in Eleventy 2.0+. Use addAsyncShortcode in older versions of Eleventy. You can also add these shortcodes to individual template engines, if you’d like!

Now you can use the image shortcode in your templates:

View this example in: Liquid Nunjucks 11ty.js Handlebars
Syntax Liquid
{% image "./src/images/cat.jpg", "photo of my cat" %}
{% image "./src/images/cat.jpg", "photo of my cat", "(min-width: 30em) 50vw, 100vw" %}

The comma between arguments is optional in Liquid templates.

Syntax Nunjucks
{% image "./src/images/cat.jpg", "photo of my cat" %}
{% image "./src/images/cat.jpg", "photo of my cat", "(min-width: 30em) 50vw, 100vw" %}

The comma between arguments is required in Nunjucks templates.

Syntax JavaScript
module.exports = function() {
let img1 = await this.image("./src/images/cat.jpg", "photo of my cat");
let img2 = await this.image("./src/images/cat.jpg", "photo of my cat", "(min-width: 30em) 50vw, 100vw");

return `${img1}
${img2}`
;
};

This image shortcode example requires an async-friendly template language and is not available in Handlebars.



And you’ll have the appropriate HTML generated for you (based on your specified Image options).

Whitespace Mode Jump to heading

Added in Image 0.7.3You can use the whitespaceMode option to strip the whitespace from the output of the <picture> element (a must-have for use in markdown files).

async function imageShortcode(src, alt, sizes) {
// […]
return Image.generateHTML(metadata, imageAttributes, {
whitespaceMode: "inline"
});
}

// Don’t copy and paste this code block!
// Some code from the above example was removed for brevity.

Synchronous Shortcode Jump to heading

INFO:
The asynchronous method is preferred—make sure you start there first! The synchronous method is included for situations that are not async-friendly (Handlebars, macros in Nunjucks, et al).
Expand to see an example of Synchronous usage.

Use Image.statsSync to get the metadata of a source even if the image generation is not finished yet:

Filename .eleventy.js
const Image = require("@11ty/eleventy-img");
function imageShortcode(src, cls, alt, sizes, widths) {
let options = {
widths: widths,
formats: ['jpeg'],
};

// generate images, while this is async we don’t wait
Image(src, options);

let imageAttributes = {
class: cls,
alt,
sizes,
loading: "lazy",
decoding: "async",
};
// get metadata even if the images are not fully generated yet
let metadata = Image.statsSync(src, options);
return Image.generateHTML(metadata, imageAttributes);
}

module.exports = function(eleventyConfig) {
eleventyConfig.addNunjucksShortcode("myImage", imageShortcode);
}

Process images as a Custom Template Jump to heading

Use Eleventy’s Custom Template Language feature to process images. This one is not yet available on the docs: do you want to contribute it?

Process images as Data Files Jump to heading

Added in v2.0.0-beta.1 Nontraditional use case. Eleventy’s Custom Data File Formats features an example of processing Images as data files to feed EXIF data into the Data Cascade. You can use the same feature to add the metadata stats returned from the Image utility directly to the Data Cascade for use in your templates.

Show the code
Filename .eleventy.js
const Image = require("@11ty/eleventy-img");
const path = require("path");

module.exports = function(eleventyConfig) {
eleventyConfig.addDataExtension("png,jpeg", {
read: false, // Don’t read the input file, argument is now a file path
parser: async imagePath => {
let stats = await Image(imagePath, {
widths: ["auto"],
formats: ["avif", "webp", "jpeg"],
outputDir: path.join(eleventyConfig.dir.output, "img", "built")
});

return {
image: {
stats
}
};
},
});

// This works sync or async: images were processed ahead of time in the data cascade
eleventyConfig.addShortcode("dataCascadeImage", (stats, alt, sizes) => {
let imageAttributes = {
alt,
sizes,
loading: "lazy",
decoding: "async",
};
return Image.generateHTML(stats, imageAttributes);
});
};

With a template my-blog-post.md and an image file my-blog-post.jpeg, you could use the above configuration code in your template like this:

Filename my-blog-post.md
{% dataCascadeImage image.stats, "My alt text" %}

Note this also means that folder/folder.jpeg would be processed for all templates in folder/* and any images stored in your global _data would also be populated into the data cascade based on their folder structure.

Advanced Usage Jump to heading

Caching Jump to heading

In-Memory Cache Jump to heading

Added in Image 0.7.0 To prevent duplicate work and improve build performance, repeated calls to the same source image (remote or local) with the same options will return a cached results object. If a request in-progress, the pending promise will be returned. This in-memory cache is maintained across builds in watch/serve mode. If you quit Eleventy, the in-memory cache will be lost.

Images will be regenerated (and the cache ignored) if:

You can disable this behavior by using the useCache boolean option:

Examples
Example of in-memory cache reuse (returns the same promise)
Filename .eleventy.js
const Image = require("@11ty/eleventy-img");

(async () => {
let stats1 = Image("./test/bio-2017.jpg");
let stats2 = Image("./test/bio-2017.jpg");

console.assert(stats1 === stats2, "The same promise");
})();
Example of in-memory cache (returns a new promise with different options)
Filename .eleventy.js
const Image = require("@11ty/eleventy-img");

(async () => {
let stats1 = Image("./test/bio-2017.jpg");
let stats2 = Image("./test/bio-2017.jpg", { widths: [300] });

console.assert(stats1 !== stats2, "A different promise");
})();

Disk Cache Jump to heading

Added in Image 1.0.0 Eleventy will skip processing files that are unchanged and already exist in the output directory. This requires the built-in hashing algorithm and is not yet supported with custom filenames. More background at Issue #51.

New tip: Re-use and persist the disk cache across Netlify builds

Dry-Run Jump to heading

Added in Image 0.7.0 If you want to try it out and not write any files (useful for testing), use the dryRun option.

Change Global Plugin Concurrency Jump to heading

const Image = require("@11ty/eleventy-img");
Image.concurrency = 4; // default is 10

Advanced control of Sharp image processor Jump to heading

Extra options to pass to the Sharp constructor or the Sharp image format converter for webp, png, jpeg, or avif.

Output animated GIF or WebP with Sharp Jump to heading

Added in Image 1.1.0 To process and output animated gif or webp images, use the animated option for the Sharp constructor.

const Image = require("@11ty/eleventy-img");
const options = {
// Your other options ...
formats: ['webp', 'gif']
sharpOptions: {
animated: true
}
}
const metadata = await Image(src, options)

Community Resources


Other pages in Plugins: