razorborg essays

Eleventy and Foam Bootstrap Image Gallery

August 28, 2022 by Jan Martin Borgersen

This is an addition to Eleventy and Foam Tips, because I needed a solution for picture galleries when writing my European Cruise Travelog.

There are many options for creating image galleries in modals out there. Likely none of them do exactly what you want. Even more likely, it's a ton of work to wire into your site, and you should spend more time writing and less time developing.

A year or so ago, I realized I could slap a Bootstrap Carousel inside a Bootstrap Modal, and voila! An image slideshow using two off-the-shelf components that I already had available to me. The hardest job was figuring out what I wanted the launcher button to look like.

Hats off to Diego for finding the same solution and putting together this handy tutorial on css-tricks.com:

Creating a Modal Image Gallery With Bootstrap Components

But, Eleventy...

I want an easy workflow to do this from Markdown content managed by Foam and published to a static website using Eleventy.

My workflow for inline images is to use Markdown Paste in VS Code. This copies an image file from the clipboard, sticks it wherever you are collecting images in your Foam repo, and creates the Markdown for an inline image. (There's also Paste Image, which is nearly identical, and doesn't hash filenames. You may like it better.)

Ideally, I could just Markdown-Paste the images I want in my gallery, do something simple, and have a gallery appear in the published site!

1. Markdown Paste

Markdown-Pasting three images produces something that looks like this:

![picture 1](/images/de9e1bd1f49872b2300ace61acc27cad8fb16a9a860d92d87adf4b260823515f.jpg)  
![picture 2](/images/f6fbfe85ee565b8d5dfa78db016bd5c463dc80a50c09bc8859d67c1bbba3326c.jpg)
![picture 3](/images/f503299044781b2f2db9fb59760d7d3f5c3c02569feed4de95df4e3c1901f1e5.jpg)

2. Shortcodes

Shortcodes are useful for decorating content in Markdown when you don't want to inline raw HTML.

If we write a shortcode that takes three arguments: an ID, a title, and an array of images, we can turn that into a gallery. Lets change the Markdown above into this:

{ % imageGallery 'images1', 'Venice Pics', [
'/images/de9e1bd1f49872b2300ace61acc27cad8fb16a9a860d92d87adf4b260823515f.jpg',
'/images/f6fbfe85ee565b8d5dfa78db016bd5c463dc80a50c09bc8859d67c1bbba3326c.jpg',
'/images/f503299044781b2f2db9fb59760d7d3f5c3c02569feed4de95df4e3c1901f1e5.jpg'
] %}

3. Writing the Shortcode

Now we just inline a bunch of HTML from .eleventy.js. Again, the hardest part here is deciding what the launcher button looks like. I'll leave that up to you.

eleventyConfig.addShortcode("imageGallery", 
function(galleryId, titleText, imageList) {

let buttonHtml = `
<button title="
${titleText}" type="button"
data-bs-toggle="modal" data-bs-target="#
${galleryId}-modal">
${titleText}
</button>
`
;

let modalInner = ``;
let active = ' active';
for (imageStr of imageList) {
modalInner += `<div class="carousel-item${active}"><img class="d-block carousel-img" src="${imageStr}"></div>`;
active = '';
}

let modalHtml = `
<div class="modal fade" id="
${galleryId}-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">
<div class="modal-body">
<div id="
${galleryId}-carousel" class="carousel slide" data-ride="carousel">
<div id="
${galleryId}-carousel-inner" class="carousel-inner">${modalInner}</div>
<button class="carousel-control-prev" type="button" data-bs-target="#
${galleryId}-carousel" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#
${galleryId}-carousel" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
</div>
</div>
</div>
</div>
`
;

return `${buttonHtml}${modalHtml}`;
});

4. See it in action!

I did something fancy with my launcher button, and here's the result: