Carousel
Provides a scroll carousel that uses native CSS scroll-snap
property.
Usage
@import "winduum/src/components/carousel/index.css" layer(components);
<div class="x-carousel flex gap-4 items-center w-full">
<button class="x-button circle muted" data-action="click->x-carousel#prev" aria-label="Prev">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18" />
</svg>
</button>
<div class="x-carousel-content gap-2 w-full" data-x-carousel-target="content">
<div class="x-image w-full rounded-md aspect-square">
<img src="https://via.placeholder.com/512" alt="" loading="lazy">
</div>
<div class="x-image w-full rounded-md aspect-square">
<img src="https://via.placeholder.com/512" alt="" loading="lazy">
</div>
</div>
<button class="x-button circle muted" data-action="click->x-carousel#next" aria-label="Next">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3" />
</svg>
</button>
</div>
<script type="module">
import { scrollPrev, scrollNext, observeCarousel } from "winduum/src/components/carousel";
const contentElement = document.querySelector('[data-x-carousel-target="content"]')
const prevElement = document.querySelector('[data-action="click->x-carousel#prev"]')
const nextElement = document.querySelector('[data-action="click->x-carousel#next"]')
observeCarousel(contentElement)
prevElement.addEventListener('click', () => scrollPrev(contentElement))
nextElement.addEventListener('click', () => scrollNext(contentElement))
</script>
Variants
Installation
Follow instructions for individual framework usage below
Examples
Basic
<div class="x-carousel flex gap-4 items-center w-full">
<button class="x-button circle muted" data-action="click->x-carousel#prev" aria-label="Prev">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18" />
</svg>
</button>
<div class="x-carousel-content gap-2 w-full" data-x-carousel-target="content">
<div class="x-image w-full rounded-md aspect-square">
<img src="https://via.placeholder.com/512" alt="" loading="lazy">
</div>
<div class="x-image w-full rounded-md aspect-square">
<img src="https://via.placeholder.com/512" alt="" loading="lazy">
</div>
</div>
<button class="x-button circle muted" data-action="click->x-carousel#next" aria-label="Next">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3" />
</svg>
</button>
</div>
<script type="module">
import { scrollPrev, scrollNext, observeCarousel } from "winduum/src/components/carousel";
const contentElement = document.querySelector('[data-x-carousel-target="content"]')
const prevElement = document.querySelector('[data-action="click->x-carousel#prev"]')
const nextElement = document.querySelector('[data-action="click->x-carousel#next"]')
observeCarousel(contentElement)
prevElement.addEventListener('click', () => scrollPrev(contentElement))
nextElement.addEventListener('click', () => scrollNext(contentElement))
</script>
Full
<div class="x-carousel flex flex-col gap-4">
<div class="flex justify-center">
<div data-x-carousel-target="counterMin"></div>/
<div data-x-carousel-target="counterMax"></div>
</div>
<div class="flex gap-4 items-center">
<button class="x-button circle muted" data-action="click->x-carousel#prev" aria-label="Prev">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18" />
</svg>
</button>
<div class="x-carousel-content gap-4 w-full" data-x-carousel-target="content">
<div class="x-image rounded-md">
<img src="https://via.placeholder.com/160x240" alt="" loading="lazy" width="160" height="240">
</div>
<div class="x-image rounded-md">
<img src="https://via.placeholder.com/160x240" alt="" loading="lazy" width="160" height="240">
</div>
<div class="x-image rounded-md">
<img src="https://via.placeholder.com/160x240" alt="" loading="lazy" width="160" height="240">
</div>
<div class="x-image rounded-md">
<img src="https://via.placeholder.com/160x240" alt="" loading="lazy" width="160" height="240">
</div>
<div class="x-image rounded-md">
<img src="https://via.placeholder.com/160x240" alt="" loading="lazy" width="160" height="240">
</div>
<div class="x-image rounded-md">
<img src="https://via.placeholder.com/160x240" alt="" loading="lazy" width="160" height="240">
</div>
</div>
<button class="x-button circle muted" data-action="click->x-carousel#next" aria-label="Next">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3" />
</svg>
</button>
</div>
<div class="justify-center flex gap-1.5 h-4 py-4" data-x-carousel-target="pagination"></div>
<progress class="x-progress sm" value="50" max="100" data-x-carousel-target="progress"></progress>
</div>
<script type="module">
import { scrollPrev, scrollNext, observeCarousel, dragCarousel, paginationCarousel, scrollCarousel } from "winduum/src/components/carousel";
const contentElement = document.querySelector('[data-x-carousel-target="content"]')
const paginationElement = document.querySelector('[data-x-carousel-target="pagination"]')
const progressElement = document.querySelector('[data-x-carousel-target="progress"]')
const counterMinElement = document.querySelector('[data-x-carousel-target="counterMin"]')
const counterMaxElement = document.querySelector('[data-x-carousel-target="counterMax"]')
const prevElement = document.querySelector('[data-action="click->x-carousel#prev"]')
const nextElement = document.querySelector('[data-action="click->x-carousel#next"]')
const pagination = {
element: paginationElement,
itemContent: '<div class="dot data-[active]:bg-error"></div>'
}
const scrollOptions = {
counterMinElement,
counterMaxElement,
progressElement,
pagination
}
dragCarousel(contentElement)
observeCarousel(contentElement)
paginationCarousel(contentElement, pagination)
scrollCarousel(contentElement, scrollOptions)
contentElement.addEventListener('scroll', () => scrollCarousel(contentElement, scrollOptions), { passive: true })
prevElement.addEventListener('click', () => scrollPrev(contentElement))
nextElement.addEventListener('click', () => scrollNext(contentElement))
</script>
Javascript API
scrollTo
- Type:
(element: HTMLElement | Element, index: number) => void
- Kind:
sync
Scroll to a snap item by its index.
scrollNext
- Type:
(element: HTMLElement | Element) => void
- Kind:
sync
Scroll to the next snap item.
scrollPrev
- Type:
(element: HTMLElement | Element) => void
- Kind:
sync
Scroll to a previous snap item.
getItemCount
- Type:
(element: HTMLElement | Element, scrollWidth: number, mathFloor: boolean) => number
- Kind:
sync
Get the number of possible scrolls inside the carousel.
observeCarousel
- Type:
(element: HTMLElement | Element, options?: ObserveCarouselOptions) => void
- Kind:
sync
Adds an observer for the carousel. Adds properties _observer
and _activeIndex
to the DOM of the carousel element
.
ObserveCarouselOptions
visibleAttribute
- Type:
string
- Default:
data-visible
A class that is added to the carousel items once they are visible.
observerOptions
- Type:
IntersectionObserverInit
- Default:
{ threshold: 0.5 }
Additional options confugration for the observer.
dragCarousel
- Type:
(element: HTMLElement | Element, options?: DragCarouselOptions) => void
- Kind:
sync
Adds a mouse dragging capability to the carousel.
DragCarouselOptions
activeAttribute
- Type:
string
- Default:
data-grabbing
paginationCarousel
- Type:
(element: HTMLElement | Element, options?: PaginationCarouselOptions) => void
- Kind:
sync
Inserts pagination indicators for the carousel to the desired element.
PaginationCarouselOptions
element
- Type:
HTMLElement | Element
- Default:
undefined
itemContent
- Type:
string
- Default:
<div aria-hidden="true"></div>
activeAttribute
- Type:
string
- Default:
data-active
autoplayCarousel
- Type:
(element: HTMLElement | Element, options?: AutoplayCarouselOptions) => void
- Kind:
sync
Adds an autoplay for the carousel.
AutoplayCarouselOptions
delay
- Type:
number
- Default:
4000
Delay in ms.
pauseElements
- Type:
HTMLElement[] | Element[]
- Default:
[]
Which elements should pause the autoplay upon hover.
scrollCarousel
- Type:
(element: HTMLElement | Element, options?: ScrollCarouselOptions) => void
- Kind:
sync
A helper function that updates various carousel states upon scroll.
ScrollCarouselOptions
observe
- Type:
ObserveCarouselOptions
- Default:
undefined
pagination
- Type:
PaginationCarouselOptions
- Default:
{ activeClass: 'active' }
progressElement
- Type:
HTMLProgressElement | Element
- Default:
undefined
counterMinElement
- Type:
HTMLElement | Element
- Default:
undefined
counterMaxElement
- Type:
HTMLElement | Element
- Default:
undefined