Carousel
A carousel displays a sequence of slides in a scrollable track. It is commonly used for featured content, hero sections, and media galleries.
Styles
Section titled “Styles”<div class="tng-carousel"> <div class="tng-carousel-track"> <div class="tng-carousel-slide"> <div class="tng-slot" style="block-size: 300px">Slide 1</div> </div> <div class="tng-carousel-slide"> <div class="tng-slot" style="block-size: 300px">Slide 2</div> </div> <div class="tng-carousel-slide"> <div class="tng-slot" style="block-size: 300px">Slide 3</div> </div> </div></div>Elements
Section titled “Elements”Carousel controls
Section titled “Carousel controls”Carousel controls render a list of item buttons used to navigate between slides. The active item displays a top progress bar that fills over time.
Use position utilities to overlay them on the carousel: add p-relative to .tng-carousel and p-absolute at-bottom inset-lg to .tng-carousel-controls.
<div class="tng-carousel p-relative"> <div class="tng-carousel-track"> <div class="tng-carousel-slide"> <div class="tng-slot" style="block-size: 300px">Slide 1</div> </div> <div class="tng-carousel-slide"> <div class="tng-slot" style="block-size: 300px">Slide 2</div> </div> <div class="tng-carousel-slide"> <div class="tng-slot" style="block-size: 300px">Slide 3</div> </div> </div> <div class="tng-carousel-controls p-absolute at-bottom inset-lg"> <button class="tng-carousel-control">Item 1</button> <button class="tng-carousel-control is-active" disabled> Item 2 </button> <button class="tng-carousel-control">Item 3</button> </div></div>Progress duration
Section titled “Progress duration”The active progress animation duration is controlled by the custom property --tng-carousel-control-progress-duration.
- Apply it on
.tng-carousel-controlsto set one duration for all items. The default is 5 seconds. - Apply it on
.tng-carousel-controlto set duration per asset.
<div class="tng-carousel-controls" style="--tng-carousel-control-progress-duration: 5s;"> <button class="tng-carousel-control">Asset 1</button> <button class="tng-carousel-control" style="--tng-carousel-control-progress-duration: 8s;" > Asset 2 </button> <button class="tng-carousel-control">Asset 3</button></div>Behavior notes
Section titled “Behavior notes”- The progress fill runs only on
.tng-carousel-control.is-active. - The bar uses rested color for remaining track and active color for completed progress.
- Hover changes indicator thickness and hover track color for non-disabled items.
- Under reduced motion, active items render at full progress without animation.
Modules
Section titled “Modules”With count indicator
Section titled “With count indicator”The count indicator can be overlaid on the carousel using the same position utilities: p-relative on .tng-carousel and p-absolute at-bottom inset-lg on .tng-count-indicator.
<div class="tng-carousel p-relative"> <div class="tng-carousel-track"> <div class="tng-carousel-slide"> <div class="tng-slot" style="block-size: 300px">Slide 1</div> </div> <div class="tng-carousel-slide"> <div class="tng-slot" style="block-size: 300px">Slide 2</div> </div> <div class="tng-carousel-slide"> <div class="tng-slot" style="block-size: 300px">Slide 3</div> </div> </div> <div class="tng-count-indicator p-absolute at-bottom inset-lg" style="width: 200px" > <div class="tng-count-indicator-helper">1 of 3</div> <div class="tng-count-indicator-dots"> <div class="is-current"></div> <div></div> <div></div> </div> <div class="tng-count-indicator-buttons"> <button class="tng-icon-button is-sm" aria-label="Previous"> <i class="tng-icon icon-chevron-left" aria-hidden="true"></i> </button> <button class="tng-icon-button is-sm" aria-label="Next"> <i class="tng-icon icon-chevron-right" aria-hidden="true"></i> </button> </div> </div></div>Recipes
Section titled “Recipes”Use <button> for item controls so keyboard and focus behavior are native.
- Add meaningful button text (or
aria-labelwhen text is not visible). - Keep the active button state synchronized with your carousel content.
- Mark the active item with
aria-current="true"(oraria-current="step") when appropriate for your UX.