Eleventy (11ty) gallery part 2 - Supporting folders

| 3 min read

Last year I wrote about how I implemented the gallery for this site.

Since I want to dump a bunch of pictures, but some are pretty thematic, I want to support folders. Thankfully 11ty is pretty flexible and with some JS magic I managed to do it. Here is how:

Adding our folders to the gallery collection

Lat time we worked on implementing a new data collection "gallery" which had this schema:

[
  {
    name: "image name",
    src: "path to the image"
  }
]

In order to support folders we want to add a folder item to our collection that holds the same information for all the pictures under it. With some node.js magic we can do it this way

// file: gallery.js imported in .eleventy.js
exports.addGalleryCollection = (eleventyConfig) => {
eleventyConfig.addCollection("gallery", () => {
const galleryPath = path.resolve(__dirname, "../src/images/gallery");
const files = fs.readdirSync(galleryPath);

return files.map((file) => {
const filePath = path.resolve(__dirname, `../src/images/gallery/${file}`);
const isDirectory = fs.lstatSync(filePath).isDirectory();
const name = file.split(".")[0];

// 👇🏻 Detect if the file is indeed a directory
if (isDirectory) {
return {
name,
src: `/gallery/folder/${file}`,
isDirectory: true,
// 👇🏻 If So add an array with the contained files
files: createDirectoryGallery(filePath, file),
};
}

return {
name,
isDirectory: false,
src: `/images/gallery/${file}`,
files: [],
};
});
});
};

// 👇🏻 Itearate over all files contained on a directory to generate our needed structure
const createDirectoryGallery = (directoryPath, directoryName) => {
const files = fs.readdirSync(directoryPath);
const gallery = [];

for (const file of files) {
if (file.includes(".txt")) continue;

const name = file.split(".")[0];
gallery.push({
name,
src: `/images/gallery/${directoryName}/${file}`,
});
}

return gallery;
};

I'm very aware that we could have done that more elegantly with recursion or other trickery, but so far it gets the job done!

Rendering our folders in the gallery view

With the data in place we now can add a bit of code to our gallery.njk template to tell it how to handle directories:

// gallery.njk

...
{% if image.isDirectory %}
<img class="image_background" src="{{ image.files[1].src }}" width="{{ image.files[1].width }}" height="{{ image.files[1].height }}" title="{{ image.files[1].name}}" alt="{{ image.files[1].name}}" />
<img class="image_background image_background--alternate" src="{{ image.files[2].src }}" width="{{ image.files[2].width }}" height="{{ image.files[2].height }}" title="{{ image.files[2].name}}" alt="{{ image.files[2].name}}" />

<div class="overlay-info">
<span class="name">📁 {{image.name}}</span>
<span class="number">{{ image.files.length }} files</span>
</div>
{% endif %}
...

First and second images will render behind our main one and with a bit of CSS we can make a cool stacked pictures effect:

// gallery.css

.image_background
{
position:absolute;
top: 0;
transform: rotate(5deg);
z-index:-1;
opacity: .7;
}

.image_background--alternate{
transform: rotate(-5deg);
}

Creating our gallery folder view

This is where it gets tricky. I wanted to reuse the gallery template since it is going to be identical, but I couldn't manage to find how to create dynamic routes in Eleventy.

What I ended up doing is creating a new template that only applies to gallery folders:

// gallery.njk

---
layout: base.njk
pagination:
data: collections.gallery
size: 1
alias: folder
title: Gallery
permalink: "gallery/folder/{{ folder.name }}/"
---
<a href="/gallery">Back to gallery</a>
<h1>{{ folder.name | capitalize }}</h1>
<p>{{ folder.description }}</p>

<ul id="gallery">
{% for image in folder.files | reverse %}
<a class="item" href="{{ image.src }}">
<img src="{{ image.src }}" width="{{ image.width }}" height="{{ image.height }}" title="{{ image.name}}" alt="{{ image.name}}" />
</a>
{% endfor %}
</ul>

Using the Pagination feature of Eleventy we can make it create a page for each of our gallery items. And there use the contents of the files array we saved in our collection to render all of our pictures.

I also tried to limit this to only folders, but didn't seem to work so well, so for now I will have to live with unnecessarily created pages for all pictures.

Enjoy!

Hope it helped you when working with this static site generator. As always you can see the result at my new flamboyant picture dump

Vilva.