Marquee
A customizable marquee effect for scrolling content horizontally or vertically
Installation
Run the following command
It will create a new file Marquee.tsx inside the components/effects directory.
mkdir -p components/effects && touch components/effects/Marquee.tsxPaste the code
Open the newly created file and paste the following code:
"use client";
 
import { cn } from "@/lib/utils";
 
interface MarqueeProps {
  className?: string;
  reverse?: boolean;
  pauseOnHover?: boolean;
  children?: React.ReactNode;
  vertical?: boolean;
  repeat?: number;
  [key: string]: any;
}
 
export default function Marquee({
  className,
  reverse,
  pauseOnHover = false,
  children,
  vertical = false,
  repeat = 4,
  ...props
}: MarqueeProps) {
  return (
    <div
      {...props}
      className={cn(
        "group flex overflow-hidden p-2 [--duration:40s] [--gap:1rem] [gap:var(--gap)]",
        {
          "flex-row": !vertical,
          "flex-col": vertical,
        },
        className
      )}
    >
      {Array(repeat)
        .fill(0)
        .map((_, i) => (
          <div
            key={i}
            className={cn("flex shrink-0 justify-around [gap:var(--gap)]", {
              "animate-marquee flex-row": !vertical,
              "animate-marquee-vertical flex-col": vertical,
              "group-hover:[animation-play-state:paused]": pauseOnHover,
              "[animation-direction:reverse]": reverse,
            })}
          >
            {children}
          </div>
        ))}
    </div>
  );
}Add the required CSS animations
You can add the animations in one of two ways:
Option 1: Global CSS
Add these animations to your global CSS file:
@keyframes marquee {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(calc(-100% - var(--gap)));
  }
}
 
@keyframes marquee-vertical {
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(calc(-100% - var(--gap)));
  }
}
 
.animate-marquee {
  animation: marquee var(--duration) linear infinite;
}
 
.animate-marquee-vertical {
  animation: marquee-vertical var(--duration) linear infinite;
}Option 2: Tailwind Config
Add these keyframes to your tailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {
      keyframes: {
        marquee: {
          from: { transform: "translateX(0)" },
          to: { transform: "translateX(calc(-100% - var(--gap)))" },
        },
        "marquee-vertical": {
          from: { transform: "translateY(0)" },
          to: { transform: "translateY(calc(-100% - var(--gap)))" },
        },
      },
      animation: {
        marquee: "marquee var(--duration) linear infinite",
        "marquee-vertical": "marquee-vertical var(--duration) linear infinite",
      },
    },
  },
  // ... rest of your config
};Props
| Prop | Type | Default | Description | 
|---|---|---|---|
| className | string | undefined | Additional CSS classes to apply | 
| reverse | boolean | false | Reverses the scroll direction | 
| pauseOnHover | boolean | false | Pauses the animation when hovering | 
| vertical | boolean | false | Switches to vertical scrolling | 
| repeat | number | 4 | Number of times to repeat the content | 
| children | React.ReactNode | required | Content to be scrolled | 
CSS Variables
| Variable | Default | Description | 
|---|---|---|
| --duration | 40s | Animation duration | 
| --gap | 1rem | Gap between repeated elements | 
Usage
import { Marquee } from "@/components/effects/Marquee";
 
export default function Example() {
  return (
    <Marquee className="bg-muted" pauseOnHover>
      <span className="px-4">Item 1</span>
      <span className="px-4">Item 2</span>
      <span className="px-4">Item 3</span>
    </Marquee>
  );
}Vertical Marquee
import { Marquee } from "@/components/effects/Marquee";
 
export default function Example() {
  return (
    <Marquee vertical className="h-[300px]">
      <span className="py-4">Item 1</span>
      <span className="py-4">Item 2</span>
      <span className="py-4">Item 3</span>
    </Marquee>
  );
}Custom Speed
You can adjust the animation speed by modifying the --duration CSS variable:
<Marquee className="[--duration:20s]">{/* Content */}</Marquee>Credits
Built by Bossadi Zenith