Carousel

Renders a carousel for presenting a sequence of items, such as images or text.

Read more Read less

If a carousel only has a single item, no controls and no pagination are rendered.

The element around the slides has tabindex="0", so that the slides can be scrolled by keyboard and not only stepped through with the controls.

Required CSS

The element with the -items-container class has to be a horizontal scroll container, since the controls and the auto rotation move the carousel by scrolling it:

.carousel-items-container {
  overflow-x: auto;
  scroll-snap-type: x mandatory;
}

.carousel-items {
  display: flex;
}

.carousel-item {
  flex: 0 0 100%;
  scroll-snap-align: center;
}

The items must not shrink. Scroll snapping is optional, but without it a slide can come to rest half shown. Whether the movement is animated depends on scroll-behavior. If you animate it, turn it off with a @media (prefers-reduced-motion) media query.

Styling

The carousel has a data-active-index attribute, and data-paused while the rotation is stopped. The visible slide has aria-current, its pagination tab has aria-selected, and with loop={false} the previous and next buttons are disabled at the ends.

The pause button changes its label, not its content. Put both icons into the slot and use a CSS selector on data-paused to pick one:

<:pause label="Pause slide show" resume_label="Resume slide show">
  <.icon name="pause" class="when-running" />
  <.icon name="play" class="when-paused" />
</:pause>
.carousel:not([data-paused]) .when-paused,
.carousel[data-paused] .when-running {
  display: none;
}

Localization

The build options carousel_roledescription, slide_roledescription, pagination_label and pagination_slide_label, and the labels of the :pause slot, default to English. They are announced by screen readers and should be translated, as should the labels of the :previous and :next slots.

Defaults

A default for the :pause, :previous or :next slot turns on rotation or the previous and next buttons for every carousel of the build, and a call cannot turn them off. If some carousels need them and others do not, build the carousel a second time under another name: with other defaults, or set no defaults and pass the slots at each call.

Maturity: Developing

The semantics follow the ARIA Authoring Practices. With pagination, the pickers are a tablist and the slides are its tab panels. Without it, the slides are groups.

Everything the pattern asks for is implemented. The level stays at :developing because the API is new and has not been proven in production yet.

Usage

<.carousel id="dog-carousel" label="Our Dogs">
  <:previous label="Previous Slide">
    <Heroicons.chevron_left />
  </:previous>
  <:next label="Next Slide">
    <Heroicons.chevron_right />
  </:next>
  <:item label="1 of 3">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_1.webp?raw=true"
      alt="A gray-muzzled dog in a camouflage coat and harness."
      ratio="16:9"
    />
  </:item>
  <:item label="2 of 3">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_2.webp?raw=true"
      alt="A small curly-haired white dog seen from the side."
      ratio="16:9"
    />
  </:item>
  <:item label="3 of 3">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_3.webp?raw=true"
      alt="A large cream-colored dog on a leash, looking up."
      ratio="16:9"
    />
  </:item>
</.carousel>

This component needs the Doggo.Carousel JavaScript hook. See Phoenix LiveView Hooks for registering it.

Keyboard

  • Left and Right - previous or next slide, with the focus on a pagination tab. With loop they wrap, without it they stop at the ends.
  • Home and End - first or last slide, with the focus on a pagination tab.

The pagination is a single tab stop. The arrow keys need the colocated hook.

<.carousel id="carousel-single-default" label="Our Dogs" pagination>
  <:pause label="Pause slide show" resume_label="Resume slide show">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-pause"
    aria-hidden="true"
  >
    <rect x="14" y="4" width="4" height="16" rx="1" />
    <rect x="6" y="4" width="4" height="16" rx="1" />
  </svg>
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-play"
    aria-hidden="true"
  >
    <polygon points="6 3 20 12 6 21 6 3" />
  </svg>
  </:pause>
  <:previous label="Previous Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-left"
    aria-hidden="true"
  >
    <path d="m15 18-6-6 6-6" />
  </svg>
  </:previous>
  <:next label="Next Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-right"
    aria-hidden="true"
  >
    <path d="m9 18 6-6-6-6" />
  </svg>
  </:next>
  <:item label="1 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_1.webp?raw=true"
      alt="A gray-muzzled dog in a camouflage coat and harness."
    />
  </:item>
  <:item label="2 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_2.webp?raw=true"
      alt="A small curly-haired white dog seen from the side."
    />
  </:item>
  <:item label="3 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_3.webp?raw=true"
      alt="A large cream-colored dog on a leash, looking up."
    />
  </:item>
  <:item label="4 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_4.webp?raw=true"
      alt="A white terrier walking along a paved street."
    />
  </:item>
</.carousel>

If looping is disabled, auto rotation stops when the last slide is reached. When the pause/resume button is clicked, the slide show starts again on the first slide.

<.carousel id="carousel-single-without-looping" label="Our Dogs" pagination>
  <:pause label="Pause slide show" resume_label="Resume slide show">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-pause"
    aria-hidden="true"
  >
    <rect x="14" y="4" width="4" height="16" rx="1" />
    <rect x="6" y="4" width="4" height="16" rx="1" />
  </svg>
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-play"
    aria-hidden="true"
  >
    <polygon points="6 3 20 12 6 21 6 3" />
  </svg>
  </:pause>
  <:previous label="Previous Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-left"
    aria-hidden="true"
  >
    <path d="m15 18-6-6 6-6" />
  </svg>
  </:previous>
  <:next label="Next Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-right"
    aria-hidden="true"
  >
    <path d="m9 18 6-6-6-6" />
  </svg>
  </:next>
  <:item label="1 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_1.webp?raw=true"
      alt="A gray-muzzled dog in a camouflage coat and harness."
    />
  </:item>
  <:item label="2 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_2.webp?raw=true"
      alt="A small curly-haired white dog seen from the side."
    />
  </:item>
  <:item label="3 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_3.webp?raw=true"
      alt="A large cream-colored dog on a leash, looking up."
    />
  </:item>
  <:item label="4 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_4.webp?raw=true"
      alt="A white terrier walking along a paved street."
    />
  </:item>
</.carousel>
<.carousel id="carousel-single-without-auto-rotation" label="Our Dogs" pagination>
  <:previous label="Previous Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-left"
    aria-hidden="true"
  >
    <path d="m15 18-6-6 6-6" />
  </svg>
  </:previous>
  <:next label="Next Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-right"
    aria-hidden="true"
  >
    <path d="m9 18 6-6-6-6" />
  </svg>
  </:next>
  <:item label="1 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_1.webp?raw=true"
      alt="A gray-muzzled dog in a camouflage coat and harness."
    />
  </:item>
  <:item label="2 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_2.webp?raw=true"
      alt="A small curly-haired white dog seen from the side."
    />
  </:item>
  <:item label="3 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_3.webp?raw=true"
      alt="A large cream-colored dog on a leash, looking up."
    />
  </:item>
  <:item label="4 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_4.webp?raw=true"
      alt="A white terrier walking along a paved street."
    />
  </:item>
</.carousel>
<.carousel
  id="carousel-single-slow-rotation"
  label="Our Dogs"
  pagination
  rotation_interval_ms={10000}
>
  <:pause label="Pause slide show" resume_label="Resume slide show">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-pause"
    aria-hidden="true"
  >
    <rect x="14" y="4" width="4" height="16" rx="1" />
    <rect x="6" y="4" width="4" height="16" rx="1" />
  </svg>
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-play"
    aria-hidden="true"
  >
    <polygon points="6 3 20 12 6 21 6 3" />
  </svg>
  </:pause>
  <:previous label="Previous Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-left"
    aria-hidden="true"
  >
    <path d="m15 18-6-6 6-6" />
  </svg>
  </:previous>
  <:next label="Next Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-right"
    aria-hidden="true"
  >
    <path d="m9 18 6-6-6-6" />
  </svg>
  </:next>
  <:item label="1 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_1.webp?raw=true"
      alt="A gray-muzzled dog in a camouflage coat and harness."
    />
  </:item>
  <:item label="2 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_2.webp?raw=true"
      alt="A small curly-haired white dog seen from the side."
    />
  </:item>
  <:item label="3 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_3.webp?raw=true"
      alt="A large cream-colored dog on a leash, looking up."
    />
  </:item>
  <:item label="4 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_4.webp?raw=true"
      alt="A white terrier walking along a paved street."
    />
  </:item>
</.carousel>
<.carousel id="carousel-single-without-pagination" label="Our Dogs">
  <:pause label="Pause slide show" resume_label="Resume slide show">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-pause"
    aria-hidden="true"
  >
    <rect x="14" y="4" width="4" height="16" rx="1" />
    <rect x="6" y="4" width="4" height="16" rx="1" />
  </svg>
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-play"
    aria-hidden="true"
  >
    <polygon points="6 3 20 12 6 21 6 3" />
  </svg>
  </:pause>
  <:previous label="Previous Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-left"
    aria-hidden="true"
  >
    <path d="m15 18-6-6 6-6" />
  </svg>
  </:previous>
  <:next label="Next Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-right"
    aria-hidden="true"
  >
    <path d="m9 18 6-6-6-6" />
  </svg>
  </:next>
  <:item label="1 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_1.webp?raw=true"
      alt="A gray-muzzled dog in a camouflage coat and harness."
    />
  </:item>
  <:item label="2 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_2.webp?raw=true"
      alt="A small curly-haired white dog seen from the side."
    />
  </:item>
  <:item label="3 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_3.webp?raw=true"
      alt="A large cream-colored dog on a leash, looking up."
    />
  </:item>
  <:item label="4 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_4.webp?raw=true"
      alt="A white terrier walking along a paved street."
    />
  </:item>
</.carousel>

If there is only a single slide, no controls are rendered.

<.carousel id="carousel-single-with-a-single-item" label="Our Dogs" pagination>
  <:pause label="Pause slide show" resume_label="Resume slide show">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-pause"
    aria-hidden="true"
  >
    <rect x="14" y="4" width="4" height="16" rx="1" />
    <rect x="6" y="4" width="4" height="16" rx="1" />
  </svg>
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-play"
    aria-hidden="true"
  >
    <polygon points="6 3 20 12 6 21 6 3" />
  </svg>
  </:pause>
  <:previous label="Previous Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-left"
    aria-hidden="true"
  >
    <path d="m15 18-6-6 6-6" />
  </svg>
  </:previous>
  <:next label="Next Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-right"
    aria-hidden="true"
  >
    <path d="m9 18 6-6-6-6" />
  </svg>
  </:next>
  <:item label="1 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_1.webp?raw=true"
      alt="A gray-muzzled dog in a camouflage coat and harness."
    />
  </:item>
</.carousel>
<.carousel id="carousel-single-without-pagination-or-auto-rotation" label="Our Dogs">
  <:previous label="Previous Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-left"
    aria-hidden="true"
  >
    <path d="m15 18-6-6 6-6" />
  </svg>
  </:previous>
  <:next label="Next Slide">
    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    class="lucide lucide-chevron-right"
    aria-hidden="true"
  >
    <path d="m9 18 6-6-6-6" />
  </svg>
  </:next>
  <:item label="1 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_1.webp?raw=true"
      alt="A gray-muzzled dog in a camouflage coat and harness."
    />
  </:item>
  <:item label="2 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_2.webp?raw=true"
      alt="A small curly-haired white dog seen from the side."
    />
  </:item>
  <:item label="3 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_3.webp?raw=true"
      alt="A large cream-colored dog on a leash, looking up."
    />
  </:item>
  <:item label="4 of 4">
    <.image
      src="https://github.com/woylie/doggo/blob/main/assets/images/dog_4.webp?raw=true"
      alt="A white terrier walking along a paved street."
    />
  </:item>
</.carousel>