ScreenshotNeo

BlogHow-to

Bootstrap Carousel Examples: How to Build a Responsive Slider

Build a responsive Bootstrap 5.3 carousel with working controls, indicators, captions, and deliberate autoplay. Learn image sizing, accessibility, and fixes for common issues.

By the ScreenshotNeo team4 October 202611 min read

A responsive Bootstrap carousel uses the Bootstrap 5.3 CSS and JavaScript bundle, a uniquely identified .carousel wrapper, a .carousel-inner, and one or more .carousel-item slides. Mark one slide .active; use responsive image sizing such as .d-block.w-100, and make every control and indicator target the wrapper’s ID. Bootstrap does not make differently sized images the same height automatically, so choose and test a consistent framing approach for your content.

This guide builds a working slider with controls, indicators, captions, responsive image framing, and optional autoplay. It uses Bootstrap 5.3.8, the version currently shown in the official setup documentation; check the version and integrity values when publishing because CDN assets can change. See the Bootstrap Carousel documentation and Bootstrap setup guide.

1. Add Bootstrap and the mobile viewport

Save this as an HTML file and replace the example image paths with images you control. The viewport declaration lets the layout use the device width. The Bootstrap bundle includes the JavaScript Popper-dependent components need; Carousel itself requires Bootstrap JavaScript.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Responsive Bootstrap carousel</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css"
        rel="stylesheet"
        integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB"
        crossorigin="anonymous">
  <style>
    /* Optional: give every slide a consistent frame. This crops images. */
    .hero-slide-image {
      width: 100%;
      aspect-ratio: 16 / 7;
      object-fit: cover;
    }
    @media (max-width: 575.98px) {
      .hero-slide-image { aspect-ratio: 4 / 3; }
    }
  </style>
</head>
<body>
  <main class="container py-4">
    <!-- Carousel markup goes here -->
  </main>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
          integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
          crossorigin="anonymous"></script>
</body>
</html>

The CDN URLs and integrity attributes above follow the current Bootstrap 5.3 setup page. If you change the Bootstrap version or CDN file, use the matching integrity value from its official setup documentation.

Place this inside the <main> element. The first item and first indicator are active. Each image has useful alternative text; use empty alt="" only when an image is decorative and its information is conveyed elsewhere.

<div id="heroCarousel" class="carousel slide" aria-label="Featured projects">
  <div class="carousel-indicators">
    <button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="0"
            class="active" aria-current="true" aria-label="Slide 1"></button>
    <button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="1"
            aria-label="Slide 2"></button>
    <button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="2"
            aria-label="Slide 3"></button>
  </div>

  <div class="carousel-inner rounded">
    <div class="carousel-item active">
      <img src="images/coastal-trail.jpg" class="d-block hero-slide-image"
           alt="A trail following the coast at sunset">
      <div class="carousel-caption d-none d-md-block">
        <h2>Coastal trail</h2>
        <p>A route along the water at sunset.</p>
      </div>
    </div>
    <div class="carousel-item">
      <img src="images/forest-path.jpg" class="d-block hero-slide-image"
           alt="A path through a green forest">
      <div class="carousel-caption d-none d-md-block">
        <h2>Forest path</h2>
        <p>A shaded walk beneath the canopy.</p>
      </div>
    </div>
    <div class="carousel-item">
      <img src="images/mountain-lake.jpg" class="d-block hero-slide-image"
           alt="A mountain reflected in a still lake">
      <div class="carousel-caption d-none d-md-block">
        <h2>Mountain lake</h2>
        <p>Still water below the peaks.</p>
      </div>
    </div>
  </div>

  <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 .d-block.w-100 image classes in Bootstrap’s examples make the image display as a block and span the available width. The custom aspect-ratio and object-fit rules above provide a consistent frame, but crop image edges; adjust the focal point or use naturally sized images if cropping would hide important content. The example switches to a taller frame on narrow screens. Choose the ratios to suit the source images and the design.

3. Choose slide sizing and responsive behavior

Bootstrap does not normalize slide dimensions. A carousel’s height can change as slides with different intrinsic image sizes become active. That may be acceptable for editorial content, but it can shift content below the slider. Pick one of these approaches deliberately:

Approach Use it when Tradeoff
Natural image dimensions Showing the complete image matters most. Slide heights can vary, moving following content.
Fixed height The design requires an exact frame size. May be too short on phones or too tall on small screens; needs responsive overrides.
aspect-ratio with object-fit: cover A consistent frame matters more than showing every edge. Some image content is cropped. Set focal positions where needed.

For responsive framing, use a width-based ratio and test at both narrow and wide viewport sizes. To keep the whole image visible, use object-fit: contain and choose a background color for any empty space. Keep important text and calls to action out of image pixels; put them in HTML captions or adjacent content so they can wrap and remain readable.

4. Add captions, indicators, and controls

Captions

Put each .carousel-caption inside its corresponding .carousel-item. The example hides captions below Bootstrap’s medium breakpoint with .d-none .d-md-block. Do not hide information or actions that users need to understand or use the page; provide that content elsewhere on small screens if necessary. Check caption contrast over every image and add a suitable background or text shadow if needed.

Indicators

Indicators are buttons within .carousel-indicators. Their data-bs-slide-to values are zero-based, so the first slide is 0. Point every button to the carousel ID, give it an accessible label, and mark the current one active with aria-current="true". Keep the indicator count and order in sync with the slides.

Controls

Use actual buttons, set type="button", and target the exact carousel ID with data-bs-target. The icon spans are decorative and hidden from assistive technology; the visually hidden labels give the buttons names. If there are multiple carousels, each must have a distinct ID, and its controls and indicators must target that ID.

5. Configure autoplay, crossfade, touch, and JavaScript

Autoplay is optional. For a manually controlled carousel, leave off data-bs-ride; the controls still work through Bootstrap’s data API. To cycle on page load, add data-bs-ride="carousel" to the wrapper. Bootstrap documents a 5,000 ms default interval, pauses cycling on hover by default, and stops cycling while the page is not visible in supporting browsers. A per-slide data-bs-interval can set a different duration in milliseconds.

<div id="autoCarousel" class="carousel slide" data-bs-ride="carousel">
  <div class="carousel-inner">
    <div class="carousel-item active" data-bs-interval="7000">...</div>
    <div class="carousel-item" data-bs-interval="5000">...</div>
  </div>
</div>

Use data-bs-ride only when automatic movement serves the content. It can make reading and interaction harder. If configuring through JavaScript instead of data attributes, initialize once and avoid initializing an autoplaying data-bs-ride carousel a second time:

const element = document.querySelector('#heroCarousel');
const carousel = new bootstrap.Carousel(element, {
  interval: false, // no automatic cycling
  ride: false,
  touch: true,
  wrap: true,
  keyboard: true
});

Bootstrap 5.3 supports options including interval, keyboard, pause, ride, touch, and wrap. Use interval: false to disable cycling in the JavaScript configuration, touch: false to disable swipe gestures, and wrap: false to stop at the first and last slide. Consult the official option and method reference for current defaults and method details. To use event listeners, initialize manually unless the autoplaying data attribute initializes the instance for you.

Add carousel-fade to the wrapper for a fade transition: class="carousel slide carousel-fade". The standard carousel slides horizontally. Respect user motion preferences: Bootstrap’s motion effects respond to prefers-reduced-motion, but verify the result in your page and avoid autoplay if movement is disruptive.

6. Accessibility and interaction checklist

Bootstrap warns that carousels can create usability and accessibility challenges. The framework does not make author markup accessible by itself; review the Bootstrap accessibility guidance alongside the component documentation.

  • Write meaningful alternative text for informative slide images; use empty alt text for decorative images whose meaning is already available.
  • Use buttons with accessible names for previous, next, and indicator controls.
  • Keep controls keyboard operable and visible against every slide. Check focus appearance and color contrast.
  • Do not make essential information available only in a caption hidden at small widths or in a slide users may never reach.
  • Make autoplay a deliberate choice. Users need enough time to read each slide and a way to pause or stop movement when needed.
  • Check the page with reduced motion enabled, with keyboard navigation, and at phone widths.
Symptom Likely cause Fix
No slide is visible No item has the active class, or the image path is wrong. Mark exactly one initial .carousel-item active and check the image request in browser developer tools.
Controls do nothing Bootstrap JavaScript is missing, the target ID does not match, or there is a JavaScript error. Load the Bootstrap bundle, compare data-bs-target with the wrapper ID, and inspect the console.
Indicators go to the wrong slide Index values are not zero-based or are out of order. Use 0 for the first slide and increment in slide order; check indicator count against slide count.
Only one of several carousels responds IDs are duplicated or controls target another carousel. Give each wrapper a unique ID and update its controls and indicators to match.
Slides jump in height Images have different intrinsic sizes and no common frame. Use a responsive aspect ratio or responsive height rules, or accept natural heights. Test the crop at multiple widths.
Captions are unreadable Text overlaps a bright or busy image, or the caption is too small. Add a contrast treatment, simplify the caption, or move essential copy outside the image area.
Carousel does not autoplay data-bs-ride is absent, the interval is disabled, or JavaScript did not load. Choose either the data attribute or a JavaScript configuration with a positive interval; check the bundle and console.
Carousel starts twice or behaves inconsistently The element is initialized manually after data attributes have already initialized it. Use one initialization path. Autoplaying data-bs-ride carousels initialize automatically.
Swipe is unavailable Touch support was disabled or another overlay intercepts gestures. Keep the touch option enabled and ensure overlays do not cover the carousel.
Old dark mode styling has no effect .carousel-dark is deprecated in Bootstrap 5.3. Set data-bs-theme="dark" on the carousel or an ancestor and verify contrast.

8. Performance, reliability, and cost

Bootstrap’s carousel code does not make large image files cheap to download. Serve appropriately sized, compressed images, avoid loading full-resolution originals into small frames, and consider lazy loading noninitial slides with loading="lazy" after checking the initial viewport and your browser support needs. Keep the first slide available quickly if it is important page content. Test layout stability: reserving a ratio or dimensions helps prevent image loading from changing the carousel height.

Autoplay adds motion and can trigger repeated image decoding or network activity if slides are not already loaded. Use only the needed number of slides and avoid unnecessarily short intervals. For reliability, keep all images reachable, use distinct carousel IDs, load the matching Bootstrap CSS and JS versions, and verify behavior with JavaScript enabled in the browser console. Bootstrap itself is free and open source; hosting, bandwidth, and image processing costs depend on where you deploy and store your assets, so there is no universal running cost for this markup.

9. Preview the result at real viewport sizes

After saving the file, serve it from your local development server and check a desktop width and a narrow phone width. Confirm that images load, controls and indicators work, captions remain legible, and the chosen crop preserves the subject. A screenshot can help review responsive states in a pull request or content workflow.

Or skip the browser setup

If you need screenshots of the finished page or other URLs, ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns PNG, JPEG, WebP, or PDF. It can accept cookie and consent banners before capture and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. AI agents can use its MCP server tools to take screenshots, inspect page information, or capture PDFs.

For this example, use the documented API call pattern and replace the URL with a page you can access. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(async fs => {
  await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
});

Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed; an MCP server lets AI agents take screenshots; and 1,000 screenshots a month are free with no card. Paid plans start at $5 for 3,000 screenshots. Every feature is on every plan; yearly billing gives two months free. Sign up for 1,000 free screenshots a month, with no card required.

FAQ

No. The slides are styled with CSS, but navigation, indicators, and cycling require Bootstrap’s JavaScript.

Yes. Give each carousel a unique ID and point that carousel’s buttons and indicators to it. Bootstrap documentation says nested carousels are not supported.

Should I use autoplay on a hero slider?

Only when automatic movement helps users. A manual carousel gives readers control; autoplay can make short captions harder to read and can be disruptive. If enabled, provide enough reading time and check reduced-motion behavior.

Why do my slides have different heights?

Bootstrap does not normalize their dimensions. Use naturally sized content, or apply a responsive frame such as an aspect ratio and decide whether cropping is acceptable.