Quick answer: A Bootstrap 5 carousel is a div.carousel.slide holding a carousel-inner of carousel-item slides — exactly one of which carries the active class. Add carousel-indicators, carousel-control-prev and carousel-control-next for dots and arrows, and the bundle JavaScript handles sliding, autoplay and swipe. The usual failures are a missing bundle script, no active class on the first slide, and slides of different heights that make the page jump.

Part of our Bootstrap series; add the framework first with getting started with Bootstrap 5 if you have not already.

The complete carousel

Three slides with dots and arrows, autoplaying every five seconds. Every piece here is optional except the wrapper, the inner and the items.

<div id="heroCarousel" class="carousel slide" data-bs-ride="carousel">

  <!-- dots -->
  <div class="carousel-indicators">
    <button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="0"
            class="active" aria-current="true"></button>
    <button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="1"></button>
    <button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="2"></button>
  </div>

  <!-- slides -->
  <div class="carousel-inner">
    <div class="carousel-item active">
      <img src="slide1.jpg" class="d-block w-100" alt="First slide">
      <div class="carousel-caption d-none d-md-block">
        <h5>First slide</h5>
        <p>A caption that hides on phones.</p>
      </div>
    </div>
    <div class="carousel-item">
      <img src="slide2.jpg" class="d-block w-100" alt="Second slide">
    </div>
    <div class="carousel-item">
      <img src="slide3.jpg" class="d-block w-100" alt="Third slide">
    </div>
  </div>

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

The controls and indicators all point back at the wrapper id through data-bs-target, so changing that id means updating it in every child. d-block w-100 on the images stops the inline-image baseline gap and makes slides fill the container — omit both and you get a thin strip of white under each image. The visually-hidden spans give the arrow buttons real labels for screen readers.

Carousel options that matter

OptionAttributeWhat it does
Autoplaydata-bs-ride="carousel"Slides automatically; default interval is 5000ms
Intervaldata-bs-interval="3000"Milliseconds per slide (per-item attribute)
Pause on hoverdata-bs-pause="hover" (default)Stops while the pointer is over it; false never pauses
Wrap arounddata-bs-wrap="true" (default)Whether next after the last returns to the first
Touch swipedata-bs-touch="true" (default)Enables swipe gestures on touch devices
Cross-fadecarousel-fade on the wrapperFades between slides instead of sliding

Set data-bs-ride="false" (or drop the attribute) when you want a manual, click-through carousel — the right choice for anything the user must read at their own pace. The cross-fade look is one class: <div id="heroCarousel" class="carousel slide carousel-fade">.

Controlling a carousel from JavaScript

const el = document.getElementById('heroCarousel');
const carousel = bootstrap.Carousel.getOrCreateInstance(el);

carousel.next();     // go forward
carousel.prev();     // go back
carousel.to(2);      // jump to slide index 2
carousel.pause();    // stop autoplay
carousel.cycle();    // resume autoplay

// know when a slide has finished
el.addEventListener('slid.bs.carousel', (e) => {
  console.log('now on slide', e.to);
});

Call pause() before you open a modal over the carousel and cycle() again when it closes, otherwise the slides keep changing behind the dialog. The events slide.bs.carousel and slid.bs.carousel fire before and after the transition; the event object carries from and to indexes. If you build a full-width slider, the same wrapper works — the Materialize take on that component is in the Materialize carousel guide for comparison.

When the carousel will not slide

  • No bundle script. Without bootstrap.bundle.min.js the slides just sit there.
  • No active class. Exactly one carousel-item must start active; with none, the carousel shows blank.
  • Uneven slide heights. Give images a fixed aspect ratio or set object-fit: cover so the page does not jump between slides.
  • Autoplay not starting. Autoplay needs data-bs-ride="carousel"; a bare data-bs-ride="true" is not valid and is ignored.

Building the rest of the page around it? The Bootstrap cards guide covers the responsive grid a hero section usually sits above, and the navbar guide covers the navigation that goes on top.

Want a reviewer for a design-heavy build? Ampersand Academy teaches front-end development one-to-one, using your own project as the curriculum.

Frequently asked questions

Why is my Bootstrap carousel not sliding?

The most common cause is a missing bootstrap.bundle.min.js script, since the sliding is JavaScript-driven. Also confirm that exactly one carousel-item has the active class — with none active the carousel shows nothing.

How do I make a Bootstrap carousel start automatically?

Add data-bs-ride set to carousel on the outer carousel div. The default interval is 5000 milliseconds between slides; override it per slide with data-bs-interval in milliseconds.

How do I stop a Bootstrap carousel from autoplaying?

Simply omit data-bs-ride, or set it to false. The carousel then only moves when the user clicks an arrow, a dot, or you call next() or prev() through the JavaScript API.

How do I make a Bootstrap carousel fade instead of sliding?

Add the carousel-fade class alongside slide on the outer carousel div. The slides then cross-fade in place rather than sliding horizontally, using the same controls and indicators.

How do I control a Bootstrap carousel with JavaScript?

Get an instance with bootstrap.Carousel.getOrCreateInstance(element) and call next(), prev(), to(index), pause() or cycle(). Listen for the slid.bs.carousel event to react after each transition finishes.