Docs
Marquee
A marquee component
requires configrequires interactionhover
Loading...
Installation
CLI
pnpm dlx shadcn@latest add https://animata.design/r/container/marquee.json
Manual
Add to your CSS
@keyframes marquee-x {
from { transform: translateX(0); }
to { transform: translateX(calc(-100% - var(--gap))); }
}
@keyframes marquee-y {
from { transform: translateY(0); }
to { transform: translateY(calc(-100% - var(--gap))); }
}
@theme {
--animate-marquee-horizontal: marquee-x var(--duration) infinite linear;
--animate-marquee-vertical: marquee-y var(--duration) linear infinite;
}Run the following command
It will create a new file called marquee.tsx inside the components/animata/container directory.
mkdir -p components/animata/container && touch components/animata/container/marquee.tsxPaste the code
Open the newly created file and paste the following code:
import { cn } from "@/lib/utils";
interface MarqueeProps extends React.HTMLAttributes<HTMLDivElement> {
/**
* Should the marquee scroll horizontally or vertically.
* If set to `true`, the marquee will scroll vertically.
*
* @default false
*/
vertical?: boolean;
/**
* The number of times to repeat the children. Set this value so that the repeated children overflow the container.
* @default 5
*/
repeat?: number;
/**
* Reverse the marquee direction.
*/
reverse?: boolean;
/**
* Pause the marquee animation on hover.
*/
pauseOnHover?: boolean;
/**
* Apply a gradient mask to the marquee.
* @default true
*/
applyMask?: boolean;
}
export default function Marquee({
children,
vertical = false,
repeat = 5,
pauseOnHover = false,
reverse = false,
className,
applyMask = true,
...props
}: MarqueeProps) {
return (
<div
{...props}
className={cn(
"group/marquee relative flex h-full w-full p-2 [--duration:10s] [--gap:12px] [gap:var(--gap)]",
{
"flex-col": vertical,
"flex-row": !vertical,
},
className,
)}
>
<style>{`
@keyframes marquee-x {
from { transform: translateX(0); }
to { transform: translateX(calc(-100% - var(--gap))); }
}
@keyframes marquee-y {
from { transform: translateY(0); }
to { transform: translateY(calc(-100% - var(--gap))); }
}
.marquee-horizontal {
animation: marquee-x var(--duration) infinite linear;
}
.marquee-vertical {
animation: marquee-y var(--duration) infinite linear;
}
.group\\/marquee:hover .marquee-pause-on-hover {
animation-play-state: paused;
}
`}</style>
{Array.from({ length: repeat }).map((_, index) => (
<div
key={`item-${index}`}
className={cn("flex shrink-0 [gap:var(--gap)]", {
"marquee-pause-on-hover": pauseOnHover,
"marquee-horizontal flex-row": !vertical,
"marquee-vertical flex-col": vertical,
})}
style={reverse ? { animationDirection: "reverse" } : undefined}
>
{children}
</div>
))}
{applyMask && (
<div
className={cn(
"pointer-events-none absolute inset-0 z-10 h-full w-full from-white/50 from-5% via-transparent via-50% to-white/50 to-95% dark:from-gray-800/50 dark:via-transparent dark:to-gray-800/50",
{
"bg-linear-to-b": vertical,
"bg-linear-to-r": !vertical,
},
)}
/>
)}
</div>
);
}Credits
Built by hari