Carousel
Create fluid, touch-enabled content sliders with Chassis CSS's carousel component, featuring smooth transitions and comprehensive accessibility support.
Introduction
Carousels in Chassis CSS deliver smooth, touch-enabled content sliders designed for modern web experiences. Built with CSS 3D transforms and intelligent JavaScript controls, carousels seamlessly integrate with your design system while maintaining optimal performance and accessibility standards.
Chassis CSS carousels operate on a performance-first architecture, using explicit JavaScript initialization to prevent unnecessary overhead while ensuring optimal loading performance. The positioning system leverages CSS 3D transforms to deliver hardware-accelerated transitions with smooth visual effects across all supported browsers.
Touch support is built into the core experience, providing native swipe gestures alongside keyboard navigation and traditional mouse controls. The autoplay system intelligently manages pause and resume behavior based on user interaction and page visibility, while comprehensive ARIA support ensures compatibility with screen readers and assistive technologies.
Chassis CSS carousels use explicit initialization to prevent performance overhead on unused components. Initialize carousels using the constructor method before user interaction. Carousels with data-cx-ride="carousel" initialize automatically on page load, so avoid duplicate initialization when using this attribute.
Note that nested carousels are not supported—consider accessibility implications and provide alternative navigation methods for complex content.
Chassis CSS respects user accessibility preferences by automatically disabling animations when the prefers-reduced-motion media query is detected. See the reduced motion guidelines in our accessibility documentation for implementation details.
Examples
Explore practical carousel implementations showcasing Chassis CSS's flexible architecture and comprehensive feature set. These examples demonstrate real-world usage patterns from basic content sliders to advanced interactive experiences.
Basic structure
This foundational example demonstrates the essential carousel structure with navigation controls. Chassis CSS recommends semantic <button> elements for optimal accessibility, though <a> elements with role="button" are supported for specific design requirements.
<div id="carouselExample" class="carousel slide">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
</div>
<button class="carousel-control-prev" type="button" data-cx-target="#carouselExample" data-cx-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-cx-target="#carouselExample" data-cx-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div> Navigation indicators
Enhance user experience with direct slide navigation through indicator controls. Indicators provide immediate access to specific slides and visual feedback about current position within the content sequence.
<div id="carouselExampleIndicators" class="carousel slide">
<div class="carousel-indicators">
<button type="button" data-cx-target="#carouselExampleIndicators" data-cx-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-cx-target="#carouselExampleIndicators" data-cx-slide-to="1" aria-label="Slide 2"></button>
<button type="button" data-cx-target="#carouselExampleIndicators" data-cx-slide-to="2" aria-label="Slide 3"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
</div>
<button class="carousel-control-prev" type="button" data-cx-target="#carouselExampleIndicators" data-cx-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-cx-target="#carouselExampleIndicators" data-cx-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div> Content captions
Add contextual information to slides with the .carousel-caption element. Chassis CSS captions integrate seamlessly with the utility system for responsive behavior. Use display utilities to control caption visibility across viewport sizes—this example uses .d-none for mobile and .medium:d-block for larger screens.
<div id="carouselExampleCaptions" class="carousel slide">
<div class="carousel-indicators">
<button type="button" data-cx-target="#carouselExampleCaptions" data-cx-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-cx-target="#carouselExampleCaptions" data-cx-slide-to="1" aria-label="Slide 2"></button>
<button type="button" data-cx-target="#carouselExampleCaptions" data-cx-slide-to="2" aria-label="Slide 3"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active">
<img src="..." class="d-block w-100" alt="...">
<div class="carousel-caption d-none medium:d-block">
<h5>First slide label</h5>
<p>Some representative placeholder content for the first slide.</p>
</div>
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
<div class="carousel-caption d-none medium:d-block">
<h5>Second slide label</h5>
<p>Some representative placeholder content for the second slide.</p>
</div>
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
<div class="carousel-caption d-none medium:d-block">
<h5>Third slide label</h5>
<p>Some representative placeholder content for the third slide.</p>
</div>
</div>
</div>
<button class="carousel-control-prev" type="button" data-cx-target="#carouselExampleCaptions" data-cx-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-cx-target="#carouselExampleCaptions" data-cx-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div> Fade transitions
Transform slide behavior with elegant fade transitions using .carousel-fade. This alternative animation style works particularly well with text-heavy content or when seeking subtle visual transitions. For optimal crossfading with certain content types, consider adding .bg-main or custom backgrounds to .carousel-item elements.
<div id="carouselExampleFade" class="carousel slide carousel-fade">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
</div>
<button class="carousel-control-prev" type="button" data-cx-target="#carouselExampleFade" data-cx-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-cx-target="#carouselExampleFade" data-cx-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div> Autoplay behavior
Chassis CSS carousels support intelligent autoplay functionality with comprehensive user interaction controls. Set the ride option to carousel for immediate autoplay on page load. The system automatically pauses on mouse hover and respects the Page Visibility API to stop cycling when pages aren't visible.
Chassis CSS recommends providing explicit pause/stop controls for autoplaying carousels to ensure compliance with WCAG 2.2 Success Criterion 2.2.2 Pause, Stop, Hide and improve user experience for all users.
<div id="carouselExampleAutoplaying" class="carousel slide" data-cx-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
</div>
<button class="carousel-control-prev" type="button" data-cx-target="#carouselExampleAutoplaying" data-cx-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-cx-target="#carouselExampleAutoplaying" data-cx-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div> Setting ride to true (rather than carousel) enables user-triggered autoplay—the carousel begins cycling only after the first user interaction, providing a balance between automation and user control.
<div id="carouselExampleRide" class="carousel slide" data-cx-ride="true">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
</div>
<button class="carousel-control-prev" type="button" data-cx-target="#carouselExampleRide" data-cx-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-cx-target="#carouselExampleRide" data-cx-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div> Timing control
Fine-tune autoplay timing with data-cx-interval attributes on individual .carousel-item elements. This feature enables dynamic pacing—for example, allowing more time for text-heavy slides while maintaining quicker transitions for simple images.
<div id="carouselExampleInterval" class="carousel slide" data-cx-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item active" data-cx-interval="10000">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item" data-cx-interval="2000">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
</div>
<button class="carousel-control-prev" type="button" data-cx-target="#carouselExampleInterval" data-cx-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-cx-target="#carouselExampleInterval" data-cx-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div> Minimal implementation
Create distraction-free content displays with slides-only carousels. This pattern works particularly well for hero sections, testimonials, or background imagery where controls might interfere with the design aesthetic. Remember to include .d-block and .w-100 classes for optimal image presentation.
<div id="carouselExampleSlidesOnly" class="carousel slide" data-cx-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
</div>
</div> Touch interaction control
Chassis CSS carousels include native touch/swipe support for mobile and tablet experiences. When touch interactions conflict with your interface design or content requirements, disable swiping by setting the touch option to false while maintaining traditional control functionality.
<div id="carouselExampleControlsNoTouching" class="carousel slide" data-cx-touch="false">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="..." class="d-block w-100" alt="...">
</div>
</div>
<button class="carousel-control-prev" type="button" data-cx-target="#carouselExampleControlsNoTouching" data-cx-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-cx-target="#carouselExampleControlsNoTouching" data-cx-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div> CSS
This component is customized exclusively through Sass variables during compilation rather than exposed CSS custom properties.
Sass variables
These Sass variables control the component's appearance and can be modified in the project's variables file before compilation.
$carousel-control-color: $fg-inverse;
$carousel-control-size: 15%;
$carousel-control-opacity: .5;
$carousel-control-hover-opacity: .9;
$carousel-control-transition: opacity .15s ease;
// hit zone = size + padding * 2
$carousel-indicator-width: 2rem; //determines hit zone
$carousel-indicator-height: .5rem; //determines hit zone
$carousel-indicator-padding-y: .5rem; //determines hit zone
$carousel-indicator-padding-x: .25rem; //determines hit zone
$carousel-indicator-border-radius: .5rem;
$carousel-indicator-margin: 0;
$carousel-indicator-opacity: .5;
$carousel-indicator-color: $fg-inverse;
$carousel-indicator-active-opacity: 1;
$carousel-indicator-transition: opacity .6s ease;
$carousel-caption-width: 70%;
$carousel-caption-color: $white;
$carousel-caption-padding-y: 1.25rem;
$carousel-caption-spacer: 1.25rem;
$carousel-control-icon-size: 2rem;
$carousel-control-prev-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='currentColor'><path d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0'/></svg>");
$carousel-control-next-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='currentColor'><path d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708'/></svg>");
$carousel-transition-duration: .6s;
$carousel-transition: transform $carousel-transition-duration ease-in-out; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)
JavaScript API
Control carousel behavior programmatically with Chassis CSS's comprehensive JavaScript interface, featuring smooth transitions, autoplay management, and accessibility controls.
Data attributes
Configure carousel behavior declaratively through data attributes for simple implementation without JavaScript initialization.
Use data-cx-slide with prev or next keywords for relative navigation, or data-cx-slide-to with numeric values for direct slide access (zero-indexed, like arrays).
Initialization
Initialize carousels programmatically for advanced control and configuration:
const carousel = new chassis.Carousel('#myCarousel')
Options
Chassis components offer flexible configuration through both data attributes and JavaScript. To use data attributes, prefix any option with data-cx- followed by the option name in kebab-case format (using hyphens instead of camelCase). For example, write data-cx-custom-class="my-class" rather than data-cx-customClass="my-class".
For more complex configurations, Chassis provides the data-cx-config attribute which accepts a JSON string of multiple settings. This approach simplifies markup when configuring several options at once. If the same option appears in both data-cx-config and as a separate data attribute (like data-cx-title), the individual attribute takes precedence. You can also use JSON values in individual attributes, such as data-cx-delay='{"show":100,"hide":200}' for more granular control.
When initializing components, Chassis merges configurations from multiple sources in this priority order: default settings, data-cx-config values, individual data-cx-* attributes, and finally any JavaScript object options. Values defined later in this sequence override earlier ones.
| Name | Type | Default | Description |
|---|---|---|---|
interval | number | 5000 | Autoplay timing in milliseconds between slide transitions. |
keyboard | boolean | true | Enable keyboard navigation (arrow keys) for carousel control. |
pause | string, boolean | "hover" | Pause behavior: "hover" pauses on mouse interaction, false disables pausing. Touch devices pause on touchend for two intervals after user interaction. |
ride | string, boolean | false | Autoplay mode: true starts after first interaction, "carousel" starts immediately on load. |
touch | boolean | true | Enable touch/swipe gestures for slide navigation on mobile devices. |
wrap | boolean | true | Continuous cycling (true) or hard stops at first/last slides (false). |
Methods
All Chassis CSS component methods are asynchronous and initiate CSS transitions. Methods return immediately when the transition begins, not when it completes. Calling methods on components that are already transitioning will be ignored to prevent conflicts. Learn more about Chassis JavaScript patterns.
Create carousel instances with comprehensive configuration options. For example, to initialize an autoplay carousel with custom timing and disabled touch support:
const myCarouselElement = document.querySelector('#myCarousel')
const carousel = new chassis.Carousel(myCarouselElement, {
interval: 2000,
touch: false
})
| Method | Description |
|---|---|
cycle | Initiates automatic cycling through carousel items from left to right. |
dispose | Completely destroys the carousel instance and removes all stored DOM data. |
getInstance | Static method returning the carousel instance associated with a DOM element: chassis.Carousel.getInstance(element). |
getOrCreateInstance | Static method that returns existing carousel instance or creates new one if uninitialized: chassis.Carousel.getOrCreateInstance(element). |
next | Advances to next slide. Returns immediately before transition completes (before slid.cx.carousel event). |
nextWhenVisible | Smart next navigation that respects page/element visibility. Returns before target slide is shown. |
pause | Halts automatic cycling while preserving current state. |
prev | Moves to previous slide. Returns immediately before transition completes (before slid.cx.carousel event). |
to | Direct navigation to specific slide by index (zero-based). Returns before target slide is shown. |
Events
Chassis CSS carousels provide comprehensive event hooks for application integration and analytics.
direction: Transition direction ("left"or"right")relatedTarget: DOM element becoming the active slidefrom: Current slide indexto: Target slide index
All events fire at the carousel element (<div class="carousel">) and include detailed transition information:
| Event type | Description |
|---|---|
slid.cx.carousel | Fired when slide transition animation completes. |
slide.cx.carousel | Fired immediately when slide transition begins. |
const myCarousel = document.getElementById('myCarousel')
myCarousel.addEventListener('slide.cx.carousel', event => {
// Access event properties for analytics or custom logic
console.log(`Sliding from ${event.from} to ${event.to}`)
})