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.tsx
Paste 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