Lessons

Lesson 6 - Featured Images

a pale green hellebore flower

There appears to be a bug where the Nunjucks templating language can't be rendered properly in <pre> blocks. Because of this, I will be excerpting the curly bracket-percent sign combos and replacing them with only percent signs. Wherever you see a percent sign in .njk code, add the relevant opening or closing curly bracket. I will also be replacing the double curly brackets with single curly brackets.

For some reason, I have the darndest time with images in Eleventy. I'll be honest up front - I'm still not sure what I did to fix the issues I was running into getting them working here. I could have sworn I tried the paths that ended up working!

That said, I'm going to show you what I have, just for the sake of reference.

File structure

content/
|--posts/
|  |--img/
|  |  |--sample-0.jpg
|  |  |--sample-1.jpg
|  |  `--etc
|  |--lesson-0-front-matter-and-urls.md
|  |--lesson-1-headings-paragraphs-and-horizontal-lines.md
|  `--etc
`--top level

Front matter

For any given post, my front matter references the image in this manner:

---
image:
  src: sample-0.jpg
  alt: moss on a fencepost
---

Image HTML transform plugin

Eleventy uses a plugin that processes images - it can handle things like resizing for you. Here's the image HTML transform plugin docs. In eleventy.config.js, you'll probably find a chunk of code like this already in place:

eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
  formats: ["jpeg"],

  widths: [640],
  failOnError: true,
  htmlOptions: {
    imgAttributes: {
      // e.g. <img loading decoding> assigned on the HTML tag will override these values.
      loading: "lazy",
      decoding: "async",
    }
  },

  sharpOptions: {
    animated: true,
  },
});

The default settings that came with the Eleventy base blog didn't set a width, which I wanted (by default, these images are almost 5k pixels wide). I also found it helpful to set failOnError to true for a little more feedback.

Passthrough copy

As I worked through this, I thought I needed a passthrough copy for a while. You don't - just let the plugin do its thing.

Templating

I needed images to show up in 3 places:

  • In the lists of posts on the home page, I wanted each post to show its featured image
  • In the "related posts" section on each individual post, I wanted each related post to show its featured image
  • And of course, I wanted the post to show its own featured image

Both of these sections use the same template, which in my project is called postlist.njk. Within the relevant links, I added the following:

% if post.data.image.src %
  <img src="/posts/img/{ post.data.image.src }" alt="{ post.data.image.alt }">
% else %
  <div class="missing-image"></div>
% endif %

Post body

The post body looks similar:

% if image.src %
<img class="featured-img" src="/posts/img/{ image.src }" alt="{ image.alt }">
% endif %

Together, that sets up featured images for posts.