ComponentsInfinite Slider

Infinite Slider

01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
01's image02's image03's image04's image05's image06's image
Terminal
npm i clsx tailwind-merge
utils/cn.ts
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
InfiniteSlider.tsx
import { cn } from "@/utils/cn";

export function InfiniteSliderExample() {
  return (
    <InfiniteSlider pauseOnHover>
      <img
        src="https://i.imgur.com/NfGQgBk.png"
        className="aspect-square w-[120px] rounded-[4px]"
        alt="01's image"
      />
      <img
        src="https://i.imgur.com/EeC1h3b.jpeg"
        className="aspect-square w-[120px] rounded-[4px]"
        alt="02's image"
      />
      <img
        src="https://i.imgur.com/4VCS3zG.jpeg"
        className="aspect-square w-[120px] rounded-[4px]"
        alt="03's image"
      />
      <img
        src="https://i.imgur.com/yWunBhl.jpeg"
        className="aspect-square w-[120px] rounded-[4px]"
        alt="04's image"
      />
      <img
        src="https://i.imgur.com/dfDyDad.jpeg"
        className="aspect-square w-[120px] rounded-[4px]"
        alt="05's image"
      />
      <img
        src="https://i.imgur.com/7N3FxDW.jpeg"
        className="aspect-square w-[120px] rounded-[4px]"
        alt="06's image"
      />
    </InfiniteSlider>
  );
}

type InfiniteSliderProps = {
  children: React.ReactNode;
  className?: string;
  pauseOnHover?: boolean;
};

function InfiniteSlider({
  children,
  className,
  pauseOnHover,
}: InfiniteSliderProps) {
  return (
    <div
      data-id="slider"
      className={cn("group relative flex gap-10 overflow-hidden", className)}
    >
      <div className="absolute left-0 w-1/12 h-full bg-gradient-to-r from-background to-transparent z-10" />

      {Array.from({ length: 15 }).map((_, i) => (
        <div
          key={i}
          className={cn(
            "flex shrink-0 animate-infinite-slider justify-around gap-10 [--gap:1rem]",
            pauseOnHover && "group-hover:[animation-play-state:paused]"
          )}
          data-id={`slider-child-${i + 1}`}
        >
          {children}
        </div>
      ))}
      <div className="absolute right-0 w-1/12 h-full bg-gradient-to-l from-background to-transparent z-10" />
    </div>
  );
}
tailwind.config.ts
{
  "animation": {
    "infinite-slider": "infinite-slider 40s linear infinite"
  },
  "keyframes": {
    "infinite-slider": {
      "from": {
        "transform": "translateX(0)"
      },
      "to": {
        "transform": "translateX(calc(-100% - var(--gap)))"
      }
    }
  }
}