RZREDZ.UI

Carousels

A row of slides seen one or a few at a time: tours, photos, reviews. The browser scrolls and snaps the row - a swipe, a wheel, the arrow keys - and the buttons move a slide back or on.

carousel on the frame, a named region; carousel-inner on the row, which takes the focus; carousel-item on each slide. Buttons with command="--prev" or "--next" and aria-controls naming the carousel move a slide, round the ends. An empty carousel-indicators fills with a button per slide. The slide in place is aria-current="true".

<div class="carousel" id="carousel-basic-tours" role="region" aria-label="Tours">
	<div class="carousel-inner" tabindex="0" aria-label="Tours">
		<div class="carousel-item"><div class="p-24 bg-primary-subtle vstack gap-8"><strong>North Bay marine park</strong><span>Kayaks, a lagoon and a viewpoint, a day by speedboat.</span></div></div>
		<div class="carousel-item"><div class="p-24 bg-success-subtle vstack gap-8"><strong>Turtle Cove snorkeling</strong><span>Two bays and a coral garden, lunch on board.</span></div></div>
		<div class="carousel-item"><div class="p-24 bg-warning-subtle vstack gap-8"><strong>Sunset cruise</strong><span>A catamaran round the south coast at dusk.</span></div></div>
	</div>
	<div class="hstack gap-8 justify-content-between">
		<button class="btn btn-icon" type="button" command="--prev" aria-controls="carousel-basic-tours" aria-label="Previous"><i class="bi bi-chevron-left" aria-hidden="true"></i></button>
		<div class="carousel-indicators"></div>
		<button class="btn btn-icon" type="button" command="--next" aria-controls="carousel-basic-tours" aria-label="Next"><i class="bi bi-chevron-right" aria-hidden="true"></i></button>
	</div>
</div>

Several at a time

Three custom properties on the carousel set the row, in the module's own stylesheet: --redz-carousel-items slides in view, --redz-carousel-gap between them and --redz-carousel-peek of the next one at the edges. carousel-center snaps a slide to the middle, carousel-auto lets each slide keep its own width.

.tour-reviews { --redz-carousel-items: 2; --redz-carousel-gap: 12px; --redz-carousel-peek: 24px; }
<div class="carousel" id="carousel-several-reviews" role="region" aria-label="Reviews">
	<div class="carousel-inner" tabindex="0" aria-label="Reviews">
		<div class="carousel-item"><div class="card card-body h-100">“The best day of our trip.” - Anna</div></div>
		<div class="carousel-item"><div class="card card-body h-100">“Kind guides and a clean boat.” - Mark</div></div>
		<div class="carousel-item"><div class="card card-body h-100">“The lagoon is worth the climb.” - Somchai</div></div>
		<div class="carousel-item"><div class="card card-body h-100">“Lunch was a surprise, a good one.” - Leila</div></div>
	</div>
	<div class="hstack gap-8 justify-content-end">
		<button class="btn btn-icon btn-sm" type="button" command="--prev" aria-controls="carousel-several-reviews" aria-label="Previous"><i class="bi bi-chevron-left" aria-hidden="true"></i></button>
		<button class="btn btn-icon btn-sm" type="button" command="--next" aria-controls="carousel-several-reviews" aria-label="Next"><i class="bi bi-chevron-right" aria-hidden="true"></i></button>
	</div>
</div>

One at a time, fading, playing

carousel-fade stacks the slides and shows the current one. carousel-overlay lays its buttons over the slides. A button with command="--play" plays the slides on every 5 seconds while it is aria-pressed="true" - written so, it plays from the start - and pauses while the pointer rests on the carousel or the focus is in it; it never plays for a person who asks for less motion.

<div class="carousel carousel-fade" id="carousel-fade-island" role="region" aria-label="The island">
	<div class="carousel-inner" tabindex="0" aria-label="The island">
		<div class="carousel-item"><div class="p-32 bg-info-subtle text-center"><strong>Beaches</strong></div></div>
		<div class="carousel-item"><div class="p-32 bg-success-subtle text-center"><strong>Waterfalls</strong></div></div>
		<div class="carousel-item"><div class="p-32 bg-warning-subtle text-center"><strong>Temples</strong></div></div>
	</div>
	<div class="carousel-overlay">
		<button class="btn btn-icon btn-sm" type="button" command="--prev" aria-controls="carousel-fade-island" aria-label="Previous"><i class="bi bi-chevron-left" aria-hidden="true"></i></button>
		<button class="btn btn-icon btn-sm" type="button" command="--next" aria-controls="carousel-fade-island" aria-label="Next"><i class="bi bi-chevron-right" aria-hidden="true"></i></button>
	</div>
	<div class="hstack gap-8 justify-content-center">
		<button class="btn btn-icon btn-sm btn-text" type="button" command="--play" aria-controls="carousel-fade-island" aria-pressed="false" aria-label="Play the slides"><i class="bi bi-play-fill" aria-hidden="true"></i><i class="bi bi-pause-fill" aria-hidden="true"></i></button>
		<div class="carousel-indicators"></div>
	</div>
</div>
  • The carousel is a named region and each slide a group named by the page's text slide - “2 of 5”; an indicator button says the same, the current one aria-current="true".
  • The row takes the focus (tabindex="0" and a name): the arrow keys scroll it, a slide at a time in a fading carousel.
  • A slide a person moves to by a button is told politely in a status of the carousel; nothing is told while it plays.
  • The play button is a toggle button, pressed while it plays; the pointer resting on the carousel, the focus inside it and a hidden page pause it (WCAG 2.2.2).
  • The buttons have no commandfor, which WebKit would announce as collapsed; their icons mirror right to left. An indicator is a 24 px target round its dot.

From css/components/carousel.css. It declares --redz-carousel-items, --redz-carousel-gap, --redz-carousel-peek on its root, never on rows or items.

It reads the theme's --redz-space-12, --redz-radius-12, --redz-space-8, --redz-border-strong, --redz-text, --redz-ease.

Bootstrap 5.3REDZ.UIChangeNote
carousel-caption-reviewthe slide's own text, laid out with utilities
carousel-control-next-reviewa btn btn-icon with command="--next" and aria-controls naming the carousel
carousel-control-next-iconbi bi-chevron-rightrenamemirrored right to left
carousel-control-prev-reviewa btn btn-icon with command="--prev" and aria-controls naming the carousel
carousel-control-prev-iconbi bi-chevron-leftrenamemirrored right to left
carousel-dark-reviewdata-theme="dark" on the carousel
carousel-item-end-removethe browser scrolls the row
carousel-item-next-removethe browser scrolls the row
carousel-item-prev-removethe browser scrolls the row
carousel-item-start-removethe browser scrolls the row
data-bs-slide="prev"command="--prev" aria-controls="ID"triggerthe id of the carousel, without commandfor
data-bs-slide="next"command="--next" aria-controls="ID"triggerthe id of the carousel, without commandfor
data-bs-slide-to-removean empty carousel-indicators makes its buttons
data-bs-ridecommand="--play" aria-pressed="true"reviewa play button pressed from the start, which a person who asks for less motion never sees play
data-bs-interval-removeslides turn every 5 seconds
bootstrap.Carouselthe --prev and --next buttonsreviewor scrollBy on carousel-inner; the row scrolls by the browser