DEV Community

Cover image for 11ty : how to use the image plugin to generate responsive images for CSS
Phil Rentier Digital
Phil Rentier Digital

Posted on • Edited on • Originally published at rentierdigital.xyz

11ty : how to use the image plugin to generate responsive images for CSS

I wanted to use the Eleventy plugin to process an image and set it as a div background.

My initial approach involved using the following Eleventy shortcode and CSS:

{​% image "bg.png", "photo", [300, 600], "(min-width: 30em) 50vw, 100vw" %}
Enter fullscreen mode Exit fullscreen mode
.background-container {
    background-image: url('/public/bg.png');
}
Enter fullscreen mode Exit fullscreen mode

I managed to make it work by placing the image and CSS in a public addPassthroughCopy directory, but this approach did not allow for automatic conversion of my images. I was seeking a more streamlined solution.

Automatic Eleventy image plugin processing

"Is there a way to have this image processed by the Eleventy plugin and set as a div background? The only (complicated) way I managed to do it is by putting the image and the CSS in a public addPassthroughCopy directory."

<style>
.background-container {
    background-image: url('/public/bg.png');
}
</style>

<div class="background-container">...</div>
Enter fullscreen mode Exit fullscreen mode

Aankhen & Darth_Mall from the discord help forum pushed me in the right direction.

Through our conversation, we explored how to use Eleventy's eleventy-img plugin to dynamically generate responsive background images. I was provided with a detailed approach to achieve this, involving:

  1. Configuring Eleventy: Setting up Eleventy to handle image processing and include CSS directly in the templates.
  2. Creating Nunjucks Templates: Defining templates to generate and include responsive images.
  3. Handling Errors: Debugging and ensuring paths and configurations were correctly set.

The initial attempts included several adjustments and corrections to ensure the configuration was working correctly.

After several iterations with chatGPT, the final solution involved:

  1. Setting Up eleventy.config.js: Including configurations for eleventy-img and custom Nunjucks filters.
  2. Creating Background Template (background.njk): A Nunjucks template to generate responsive CSS.
  3. Creating HTML Page (post.njk): An HTML template to use the generated CSS for responsive background images.

The final working solution was documented thoroughly and shared in Markdown format to ensure it could be easily shared and understood.

Documentation Content

This documentation explains how to configure Eleventy to use responsive background images with the eleventy-img plugin. You will learn how to define Nunjucks templates to generate images in different sizes and formats, and then include them in your pages with the appropriate styles.

Prerequisites: Node 18+ is required for Eleventy v3 and the ESM syntax used throughout this guide.

Update (2026): Eleventy v3 now ships with eleventyImageTransformPlugin, which automatically transforms all <img> tags in your HTML output — no shortcode needed. See the dedicated section below for details. However, this plugin does not handle CSS background-image — that's where the custom filter approach in this article remains essential.

Configure eleventy.config.js (or eleventy.config.images.js)

Create or update your eleventy.config.js file to include the following configuration:

// eleventy.config.js (ESM — Eleventy v3+)
import path from "path";
import eleventyImage from "@11ty/eleventy-img";

function relativeToInputPath(inputPath, relativeFilePath) {
  let split = inputPath.split("/");
  split.pop();
  return path.resolve(split.join(path.sep), relativeFilePath);
}

function isFullUrl(url) {
  try {
    new URL(url);
    return true;
  } catch (e) {
    return false;
  }
}

export default function (eleventyConfig) {
  const formats = ["avif", "webp", "auto"];

  // Eleventy Image shortcode
  // https://www.11ty.dev/docs/plugins/image/
  eleventyConfig.addAsyncShortcode(
    "image",
    async function imageShortcode(src, alt, widths, sizes) {
      const input = isFullUrl(src)
        ? src
        : relativeToInputPath(this.page.inputPath, src);

      const metadata = await eleventyImage(input, {
        widths: widths || ["auto"],
        formats,
        outputDir: "./dist/img/",
      });

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

      return eleventyImage.generateHTML(metadata, imageAttributes);
    }
  );

  // Custom filter to generate CSS with media queries
  // This is the key part — eleventyImageTransformPlugin does NOT handle CSS backgrounds
  eleventyConfig.addNunjucksAsyncFilter(
    "imageCSS",
    async function (src, sizes, formats, callback) {
      const input = isFullUrl(src)
        ? src
        : path.resolve(".", src);

      const metadata = await eleventyImage(input, {
        widths: sizes,
        formats: formats,
        outputDir: "./dist/img/",
      });

      let css = sizes
        .map((size, index) => {
          if (metadata[formats[0]][index]) {
            return `@media (min-width: ${size}px) {
          .background-container {
            background-image: url('${metadata[formats[0]][index].url}');
          }
        }`;
          } else {
            console.error(
              `Error: No metadata found for format ${formats[0]} and size index ${index}`
            );
            return "";
          }
        })
        .join("\n");

      callback(null, css);
    }
  );
}
Enter fullscreen mode Exit fullscreen mode

The Modern Alternative: eleventyImageTransformPlugin

Starting with Eleventy v3, there's a simpler way to handle standard <img> tags — no shortcode required. The eleventyImageTransformPlugin automatically processes all images found in your HTML output:

// eleventy.config.js
import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";

export default function (eleventyConfig) {
  eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
    extensions: "html",
    formats: ["avif", "webp", "auto"],
    widths: ["auto"],
    defaultAttributes: {
      loading: "lazy",
      decoding: "async",
    },
  });
}
Enter fullscreen mode Exit fullscreen mode

Just write regular <img> tags in your templates and the plugin handles the rest — generating multiple formats and sizes, wrapping in <picture>, and adding the right attributes.

Important limitation: this plugin only processes <img> tags in HTML output. It does not handle CSS background-image properties. For responsive CSS backgrounds, you still need the custom imageCSS filter described above — and that's exactly what makes this guide valuable beyond the official docs.

Creating Templates

1. Background Template (background.njk)

Create a file _includes/layouts/background.njk with the following content:

{​% set sizes = [300, 600, 1200] %}
{​% set formats = ["jpeg"] %}
{​% set imagePath = imagebg %}

{{ imagePath | imageCSS(sizes, formats) | safe }}
Enter fullscreen mode Exit fullscreen mode

2. HTML Page (post.njk)

Create a file post.njk with the following content:

---
title: "CSS background"
description: "CSS bg"
layout: layouts/post.njk
tags: posts
backgroundImage: "my-bg.png"
---

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ title }}</title>
    <style>
        .background-container {
            background-size: cover;
            background-position: center;
            width: 100%;
            height: 100vh;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            color: white;
            font-size: 2em;
        }

        .background-container p,
        .background-container input,
        .background-container button {
            margin: 10px;
        }

        .background-container input {
            padding: 10px;
            font-size: 1em;
        }

        .background-container button {
            padding: 10px 20px;
            font-size: 1em;
            cursor: pointer;
        }

        {​% set imagebg = backgroundImage %}
        {​% include "layouts/background.njk" %}
    </style>
</head>
<body>
    <div class="background-container">
        <p>YES</p>
        <input type="text" placeholder="Ask your question here" />
        <button>Submit</button>
    </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Conclusion

By following these steps, you will have configured Eleventy to use responsive background images.

The configuration allows you to generate different sizes and formats of images and include them in the CSS with media queries for optimal display on various devices.

Verification

  1. Check Paths and Permissions:

    • Ensure the public/img folder exists and permissions are set correctly.
    • Verify that the images are actually copied into the output directory _site/img.
  2. Debugging and Logs:

    • Use the logs generated by eleventy.config.js to verify that images are generated correctly and paths are accurate.
    • In case of issues, use error messages and logs to identify and fix configuration or path access errors.

What I Learned from This Experience

From this experience, I learned the importance of leveraging Eleventy's flexibility and plugins to create more efficient and streamlined solutions. Initially, I faced the challenge of processing and converting images automatically while integrating them as responsive background images in my project.

The journey involved understanding and implementing the eleventy-img plugin, configuring custom Nunjucks filters, and writing templates that dynamically generate the necessary CSS for different viewport sizes.

The key takeaways from this process include:

  • Configuring Eleventy Plugins: Gaining a deeper understanding of how to set up and configure plugins like eleventy-img for automatic image processing.
  • Template Creation: Learning how to create Nunjucks templates that can dynamically generate CSS and HTML content.
  • Responsive Design: Implementing responsive design techniques using media queries and dynamically generated CSS for different image sizes.
  • Debugging and Error Handling: Handling configuration and syntax errors effectively to ensure the smooth functioning of the project.

This experience also reinforced the value of community support (ty Aankhen & Darth_Mall) and documentation. Engaging with the Eleventy community and referring to various examples and documentation provided crucial insights and guidance throughout the process.

A Word on Eleventy

Eleventy is a highly flexible and powerful static site generator that provides a great balance between simplicity and functionality. Its ability to work seamlessly with various templating engines like Nunjucks, and its extensive plugin ecosystem, make it an excellent choice for developers looking to create fast, efficient, and highly customizable websites.

Eleventy's minimalist approach allows developers to build projects with minimal configuration while still offering the power to handle complex requirements. Whether you're a seasoned developer or just starting out, Eleventy's intuitive and straightforward workflow makes it a joy to work with.

Overall, this experience has been both educational and rewarding, showcasing the true potential of Eleventy in creating dynamic and responsive web solutions.

PS: Without ChatGPT, I would never have managed. Thanks to this experience, even a non-developer like me can now achieve complex tasks and improve my skills.

Top comments (0)