carouselcn

Image Gallery

A photo gallery carousel with thumbnail navigation.

Mountain landscape
Forest path
Lake reflection
Green hills

Use Case

Image galleries are perfect for:

  • Product photo galleries
  • Portfolio showcases
  • Property listings
  • Event photography

Features

  • Full-width images - Each slide displays a single image
  • Thumbnail navigation - Custom thumbnails using useCarousel hook
  • Aspect ratio container - Consistent 4:3 aspect ratio
  • Hover states - Visual feedback on thumbnail interaction

Implementation

import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNavigation,
  useCarousel,
} from "@/components/ui/carousel";

const images = [
  { src: "/photos/image-1.jpg", alt: "Photo 1" },
  { src: "/photos/image-2.jpg", alt: "Photo 2" },
  // ... more images
];

function ThumbnailIndicator() {
  const { index, setIndex, itemsCount } = useCarousel();

  return (
    <div className="flex justify-center gap-2 pt-4">
      {images.slice(0, itemsCount).map((image, i) => (
        <button
          key={i}
          onClick={() => setIndex(i)}
          className={`h-12 w-16 overflow-hidden rounded-md border-2 transition-all ${
            index === i
              ? "border-zinc-900 dark:border-zinc-100"
              : "border-transparent opacity-60 hover:opacity-100"
          }`}
        >
          <img
            src={image.src}
            alt={image.alt}
            className="h-full w-full object-cover"
          />
        </button>
      ))}
    </div>
  );
}

export function ImageGallery() {
  return (
    <div className="relative w-full max-w-xl">
      <Carousel>
        <CarouselContent>
          {images.map((image, index) => (
            <CarouselItem key={index}>
              <div className="aspect-[4/3] overflow-hidden rounded-xl">
                <img
                  src={image.src}
                  alt={image.alt}
                  className="h-full w-full object-cover"
                />
              </div>
            </CarouselItem>
          ))}
        </CarouselContent>
        <CarouselNavigation alwaysShow />
        <ThumbnailIndicator />
      </Carousel>
    </div>
  );
}

Tips

  • Use aspect-[4/3] or aspect-video for consistent image dimensions
  • The useCarousel hook allows building fully custom indicators
  • Consider lazy loading images for performance with large galleries

On this page