LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 2117 min read

Carousel

Learn how to build a Bootstrap carousel slideshow with indicators, controls, captions, and auto-cycling images.

Introduction

A carousel is a slideshow component for cycling through a series of images or content, such as a hero banner on a landing page. Bootstrap's carousel is built with CSS 3D transforms and a small amount of JavaScript, and it supports touch swiping on mobile devices out of the box. In this lesson you will build a complete carousel step by step: the slide wrapper, indicators, controls, captions, and the options that control how it auto-cycles.

What You Will Learn
  • The three required parts of a carousel: indicators, inner slides, and controls.
  • How to add clickable indicators and prev/next arrows.
  • How to add captions to individual slides.
  • How to control auto-cycling with data-bs-interval and data-bs-ride.
  • The crossfade and dark carousel variants.

Basic Carousel Structure

Every carousel needs a wrapping .carousel element with a unique id, a .carousel-inner container, and one or more .carousel-item elements inside it. Exactly one .carousel-item must carry the .active class, or nothing will show.

<div id="mainCarousel" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="slide-1.jpg" class="d-block w-100" alt="Mountain landscape at sunrise">
</div>
<div class="carousel-item">
<img src="slide-2.jpg" class="d-block w-100" alt="City skyline at night">
</div>
<div class="carousel-item">
<img src="slide-3.jpg" class="d-block w-100" alt="Beach with palm trees">
</div>
</div>
</div>
Result

Click Run to see what this code prints.

Adding Indicators

Indicators are the small clickable dots at the bottom of the carousel that let users jump directly to a slide. Each <button> needs data-bs-target pointing to the carousel's id and data-bs-slide-to with the zero-based slide index. The button matching the active slide should carry class="active" and aria-current="true".

<div id="mainCarousel" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-indicators">
<button type="button" data-bs-target="#mainCarousel" data-bs-slide-to="0"
class="active" aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-bs-target="#mainCarousel" data-bs-slide-to="1"
aria-label="Slide 2"></button>
<button type="button" data-bs-target="#mainCarousel" data-bs-slide-to="2"
aria-label="Slide 3"></button>
</div>
<div class="carousel-inner">
<!-- carousel-item elements -->
</div>
</div>

Previous/Next Controls

The left and right arrow controls are two <button> elements with data-bs-target pointing to the carousel and data-bs-slide set to "prev" or "next". Each includes a visually hidden .visually-hidden span so screen reader users hear "Previous" or "Next" instead of nothing.

<button class="carousel-control-prev" type="button"
data-bs-target="#mainCarousel" 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="#mainCarousel" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>

Captions

Add a .carousel-caption element inside a .carousel-item to overlay a heading and short text on top of the slide. Captions are hidden below the md breakpoint by default (d-none d-md-block) so they do not clutter small screens.

<div class="carousel-item active">
<img src="slide-1.jpg" class="d-block w-100" alt="Mountain landscape at sunrise">
<div class="carousel-caption d-none d-md-block">
<h5>First Slide Label</h5>
<p>Some representative text for the first slide.</p>
</div>
</div>

Controlling Auto-Cycling

Adding data-bs-ride="carousel" to the root element starts auto-cycling as soon as the page loads. Use data-bs-ride="true" instead if you want it to start only after the first manual interaction. Each slide accepts its own data-bs-interval (in milliseconds) to override the default 5000ms timer, and data-bs-touch="false" disables swipe gestures.

<div id="mainCarousel" class="carousel slide" data-bs-ride="carousel" data-bs-interval="4000">
<div class="carousel-inner">
<div class="carousel-item active" data-bs-interval="10000">
<img src="slide-1.jpg" class="d-block w-100" alt="...">
</div>
<div class="carousel-item" data-bs-interval="2000">
<img src="slide-2.jpg" class="d-block w-100" alt="...">
</div>
</div>
</div>
AttributePurpose
data-bs-ride="carousel"Auto-cycles starting on page load
data-bs-intervalMilliseconds between slides (default 5000)
data-bs-touch="false"Disables swipe support on touch devices
data-bs-wrap="false"Stops cycling instead of looping back to the first slide

Crossfade Transition

By default slides transition with a horizontal slide animation. Add the .carousel-fade class to the root element to crossfade slides in and out instead.

<div id="fadeCarousel" class="carousel slide carousel-fade" data-bs-ride="carousel">
<!-- carousel-inner and slides as usual -->
</div>

Dark Variant

Add .carousel-dark to invert the controls, indicators, and captions to dark text/icons for use on lighter background images.

<div id="darkCarousel" class="carousel slide carousel-dark" data-bs-ride="carousel">
<!-- indicators, inner, controls -->
</div>

Common Mistakes

Avoid These Mistakes
  • Forgetting to mark exactly one .carousel-item as .active — without it, no slide renders.
  • Mismatched ids between the carousel root and the data-bs-target selectors on indicators and controls.
  • Using multiple carousels on one page with the same id, which breaks the data-bs-target references.
  • Not adding alt text to slide images, hurting accessibility and SEO.
  • Forgetting w-100 or d-block on <img>, which can leave inline spacing gaps beneath slides.

Best Practices

  • Give every carousel a unique, descriptive id (e.g. #heroCarousel, #testimonialCarousel).
  • Keep the number of slides small (3-5) — long carousels hurt engagement and page weight.
  • Optimize and lazy-load carousel images since they are often the largest assets on a page.
  • Always include visually-hidden text on prev/next controls for screen readers.
  • Consider disabling auto-cycling (omit data-bs-ride) for content-heavy carousels users need time to read.

Frequently Asked Questions

Yes, this is the default behavior — Bootstrap pauses auto-cycling on mouseenter and resumes on mouseleave automatically.

Yes. A .carousel-item can contain any HTML, including cards, text blocks, or embedded video, not just <img> tags.

Add data-bs-wrap="false" to the root element so it stops at the last slide instead of returning to the first.

Key Takeaways

  • A carousel needs a root .carousel element, a .carousel-inner wrapper, and .carousel-item slides with exactly one marked .active.
  • Indicators and controls both reference the carousel by matching data-bs-target to its id.
  • data-bs-ride and data-bs-interval control whether and how fast the carousel auto-cycles.
  • .carousel-fade and .carousel-dark are built-in visual variants requiring no extra JavaScript.

Summary

The carousel component lets you build an interactive slideshow using only HTML data attributes, with Bootstrap's JavaScript handling the sliding, indicators, and touch gestures behind the scenes. Next, you will learn about tooltips and popovers — two lightweight components for surfacing extra information on hover or click.

Next Lesson →

Tooltips & Popovers