Bootstrap 5 Carousel: position captions outside (i.e. below) the images

(If you want to get right to the point, a full code example is provided at the bottom of this post.)

I’m not a Bootstrap expert. During most of its evolution, I’ve mostly ignored it in favor of rolling my own… everything. I finally really embraced Bootstrap when I had a rush project in October 2022 that was way too precisely designed to work with WordPress, especially Gutenberg. (And the client didn’t need editing capabilities.) So I decided to hand-code it, but to use Bootstrap to… uh… bootstrap my HTML/CSS layouts.

I think Bootstrap 5 is excellent. I wish Gutenberg was built on top of it instead of the idiosyncratic house of cards it’s actually built on, but whatever.

As it happens, I’m actually now using Bootstrap 5 with Gutenberg for some custom blocks, specifically a Carousel block. One of the options I want to provide in my block is the ability to show the carousel’s captions and controls outside of the image, but apparently, at least with Bootstrap 5, that’s not an option.

I decided to Google for a quick solution before creating my own and I came across… this. I’m sure it gets the job done, but it seems severely over-engineered, so here I’m presenting my own comparatively simple, CSS-only solution.

Basically there are two things you need to do: 1) move the absolute-positioned caption text below the image, and 2) add padding to the bottom of the container, so the caption has somewhere to go instead of just overlapping the content below it.

Let’s start with the second item first:

.carousel { padding-bottom: 4rem; }

There may be some trial and error here, as you need to make sure you’re accommodating captions of varying length. I will admit this is not fully thought out here, and unlike the rest of what is about to follow, it may be a deal breaker under certain circumstances. But let’s assume your captions are a fairly consistent length, and you can determine how much padding you need.

Getting the caption pushed below the images is easy…

.carousel-caption { top: 100%; }

…except, oops, vertical overflow is hidden. Let’s fix that:

.carousel-inner { overflow: visible; }

Of course, if you have your transition effect set to slide (which is the default), that now spews stuff all over the page in an ugly way. But we can fix that by hiding overflow on the outer carousel element instead:

.carousel { overflow: hidden; }

You might, at this point, wonder why I didn’t just set overflow-y: visible on .carousel-inner which seems perfectly reasonable, and which, of course, I tried. But for reasons I couldn’t be bothered with investigating, that ended up causing .carousel-inner to just show a vertical scrollbar and not display the caption unless you scrolled it. Ugh. No matter, the above takes care of it.

That’s pretty much it, as far as the captions go. But if you’re using the controls (previous/next arrows) or indicators (dots/lines for the number of slides and current selection), you’ll notice there’s some weirdness to their placement, so let’s fix that too. The indicators just get shoved to the bottom of the container, so your bottom padding can accommodate that. But if you want to move them back up onto the image, you just need to offset that extra padding, like this:

.carousel-indicators { bottom: 4rem; }

Make that value the same as the bottom padding you added to .carousel itself.

As for the controls, since you’ve made the overall container taller, they’re now a bit too low rather than being vertically centered on the image. Guess what… setting their bottom value to match the extra bottom padding fixes their placement too!

.carousel-control-next, .carousel-control-prev { bottom: 4rem; }

So, putting it all together as concisely as possible, here’s what we have:

.carousel { overflow: hidden; padding-bottom: 4rem; }
.carousel-caption { top: 100%; }
.carousel-inner { overflow: visible; }
.carousel-control-next, .carousel-control-prev, .carousel-indicators { bottom: 4rem; }