GooseUI

Carousel

New

A zero-dependency carousel with drag-to-scroll, auto-play, and accessible navigation built on CSS scroll-snap.

Browser Support

Widely available since 2022
scroll-snap

Learn more about Baseline browser support.

Preview

Slide 1
Slide 2
Slide 3
Slide 4
Slide 5

Installation

npm
pnpm
yarn
bun
npx shadcn@latest add @gooseui/carousel

Usage

import {
  Carousel,
  CarouselItem,
  CarouselPrevious,
  CarouselNext,
  CarouselDots,
} from "@/components/ui/carousel"

export default function Example() {
  return (
    <Carousel>
      <CarouselItem>Slide 1</CarouselItem>
      <CarouselItem>Slide 2</CarouselItem>
      <CarouselItem>Slide 3</CarouselItem>
      <CarouselPrevious />
      <CarouselNext />
      <CarouselDots />
    </Carousel>
  )
}

Examples

With Progress Bar

Slide 1
Slide 2
Slide 3
Slide 4
Slide 5
1/5
<Carousel>
  {items.map((item) => (
    <CarouselItem key={item.id}>{item.content}</CarouselItem>
  ))}
  <CarouselPrevious />
  <CarouselNext />
  <CarouselProgress />
  <CarouselCounter />
</Carousel>

Number Indicators

Slide 1
Slide 2
Slide 3
Slide 4
Slide 5
<CarouselDots variant="numbers" />

Line Indicators

Slide 1
Slide 2
Slide 3
Slide 4
Slide 5
<CarouselDots variant="line" />

Multiple Items

1
2
3
4
5
<CarouselItem size="1/3">
  {/* Shows 3 items at once */}
</CarouselItem>

Auto-Play with Loop

Slide 1
Slide 2
Slide 3
Slide 4
Slide 5
<Carousel autoPlay={3000} loop>
  {/* Auto-advances every 3 seconds */}
</Carousel>

Vertical

Slide 1
Slide 2
Slide 3
Slide 4
Slide 5
<Carousel orientation="vertical" className="h-[400px]">
  {/* Vertical scrolling */}
</Carousel>

Features

  • CSS Scroll Snap — Native scroll snapping for smooth, performant scrolling (96.4% browser support)
  • Drag to Scroll — Mouse drag support with click prevention after dragging
  • Keyboard Navigation — Arrow keys for prev/next slide
  • Auto-Play — Optional auto-advance with pause on hover
  • Loop — Optional infinite loop mode
  • Multiple Indicators — Dots, lines, numbers, progress bar, counter
  • Accessible — ARIA roles, labels, and keyboard support
  • Vertical Mode — Supports both horizontal and vertical orientation

Props

Carousel

PropTypeDefaultDescription
orientation"horizontal" | "vertical""horizontal"Scroll direction
draggablebooleantrueEnable drag-to-scroll
loopbooleanfalseLoop to start/end
autoPlaynumber0Auto-play interval in ms
pauseOnHoverbooleantruePause auto-play on hover

CarouselItem

PropTypeDefaultDescription
size"full" | "1/2" | "1/3" | "1/4" | "auto""full"Item width

CarouselDots

PropTypeDefaultDescription
variant"dots" | "line" | "numbers""dots"Indicator style

useCarousel Hook

Access carousel state and controls programmatically:

import { useCarousel } from "@/components/ui/carousel"

function CustomControls() {
  const {
    scrollPrev,
    scrollNext,
    scrollTo,
    activeIndex,
    itemCount,
    canScrollPrev,
    canScrollNext,
  } = useCarousel()

  return (
    <div>
      <button onClick={scrollPrev} disabled={!canScrollPrev}>
        Previous
      </button>
      <span>{activeIndex + 1} / {itemCount}</span>
      <button onClick={scrollNext} disabled={!canScrollNext}>
        Next
      </button>
    </div>
  )
}

Implementation Notes

This carousel uses CSS Scroll Snap for native scroll snapping with JavaScript for navigation controls. This approach ensures 96.4% browser support while providing smooth, performant scrolling.

CSS Features Used

  • scroll-snap-type: x mandatory — Snap alignment
  • snap-start — Item snap points
  • overscroll-behavior: contain — Prevent page scroll

Future CSS Carousels (Chrome 135+)

New CSS features like ::scroll-button, ::scroll-marker, and scroll-state() queries enable pure-CSS carousels but are not yet Baseline.

See Chrome CSS Carousel demos