Configuring responsive and optimized images with Eleventy
This post is part of a multi-part series on how I built my site using Eleventy. These are all the posts in the series. Check them out if that's your jam.
08/31/2021 Updated the .eleventy.js code I'm currently using.
Previously, we built our base project and got the initial site setup. Today, let's configure responsive images using the eleventy-img plugin.
Requirements
I want to write about hikes, bicycle trips and vacations on my blog. Those types of posts could have a fair number of images, and since I care about performance, I want my site to serve the appropriately sized image for the device viewing the content. There's no need to serve a mobile user the big desktop sized image!
Next, I want to store the images for a post, with the markdown file that contains the text. I feel that this is a little bit different requirement than others but I want to be able to just pickup the posts directory and everything is together, in a logical manner.
Finally, I want the short-code to be as easy and straight forward as possible when writing posts, and I'm willing to work harder during the setup to make that happen. I added some extra logic to my .eleventy.js
file. I've written two versions of my shortcode. The old version in existing posts has the full path to the image file that I want eleventy-img
to process. New posts will allow me to just indicate the file name of the image and the assumed directory will be in the /images directory relative to where the post's index.md file is located. Let's get started!
Install eleventy-img
You can follow along on the official documentation, eleventy-img.
npm install @11ty/eleventy-img
Here's the configuration for .eleventy.js. I started with How to optimize images on eleventy (11ty) as my starting point and have made adjustments for my own use case.
// .eleventy.js
const Image = require("@11ty/eleventy-img");
const localDir = "../obsolete29.com.v2"
async function imageShortcode(src, alt, sizes = "100vw") {
let sourceDir = this.page.inputPath.replace('index.md', '')
let sourcePath = sourceDir + 'images/' + src;
let metadata = await Image(sourcePath, {
widths: [360, 651, 740],
formats: ["web[", "jpeg"],
urlPath: "/assets/images/",
outputDir: localDir + "/assets/images/"
});
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, {
whitespaceMode: "inline"
});
}
module.exports = function(eleventyConfig) {
eleventyConfig.addNunjucksAsyncShortcode("myImage", imageShortcode);
return {
dir: {
input: "src",
output: localDir
},
markdownTemplateEngine: "njk"
};
}
The code
Now I'm able to use the short code in my post markdown like this:
{% image lily.jpg, Photo of Lily on the back patio with an oil lamp flame. %}
When we build our site, eleventy-img replaces the image tag with this HTML:
<!-- html output -->
<picture>
<source type="image/avif" srcset="/assets/images/27103ff9-375.avif 375w, /assets/images/27103ff9-701.avif 701w, /assets/images/27103ff9-967.avif 967w, /assets/images/27103ff9-1200.avif 1200w, /assets/images/27103ff9-1220.avif 1220w, /assets/images/27103ff9-1468.avif 1468w, /assets/images/27103ff9-1620.avif 1620w, /assets/images/27103ff9-1772.avif 1772w, /assets/images/27103ff9-1804.avif 1804w" sizes="100vw">
<source type="image/jpeg" srcset="/assets/images/27103ff9-375.jpeg 375w, /assets/images/27103ff9-701.jpeg 701w, /assets/images/27103ff9-967.jpeg 967w, /assets/images/27103ff9-1200.jpeg 1200w, /assets/images/27103ff9-1220.jpeg 1220w, /assets/images/27103ff9-1468.jpeg 1468w, /assets/images/27103ff9-1620.jpeg 1620w, /assets/images/27103ff9-1772.jpeg 1772w, /assets/images/27103ff9-1804.jpeg 1804w" sizes="100vw">
<img alt="Photo of Lily on the back patio with an oil lamp flame." loading="lazy" decoding="async" src="/assets/images/27103ff9-375.jpeg" width="1804" height="1353">
</picture>
Neat!
Further reading
I found Complete Guide to Responsive Images! helpful as I was figuring out which markup I wanted to use. I also enjoyed reading Automating Image Optimization Workflow.
Ok, that's it for now! Thanks for reading.
This post is part of a multi-part series on how I built my site using Eleventy. These are all the posts in the series. Check them out if that's your jam.