Infinite Marquee
Infinite Marquee
Infinite Marquee
- React
- Typescript
- GSAP
- ScrollTrigger Plugin
- useGSAP Plugin
- Tailwind CSS
components/infinite-marquee.tsx
import React, { useRef } from "react";
import gsap from "gsap";
import { SplitText } from "gsap/SplitText";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { useGSAP } from "@gsap/react";
gsap.registerPlugin(SplitText, ScrollTrigger);
interface InfiniteMarqueeProps {
children: React.ReactNode;
duration?: number;
className?: string;
}
export function InfiniteMarquee({
children,
duration = 10,
className,
}: InfiniteMarqueeProps) {
const containerRef = useRef<HTMLDivElement>(null);
useGSAP(
() => {
if (!containerRef.current) return;
const container = containerRef.current!;
const elements = Array.from(container.children);
if (elements.length === 0) return;
gsap.to(elements, {
xPercent: -100,
duration,
repeat: -1,
ease: "none",
});
},
{ scope: containerRef, dependencies: [duration] },
);
return (
<div
ref={containerRef}
className={`overflow-hidden w-lg flex ${className ?? ""}`.trim()}
>
{children}
</div>
);
}
<InfiniteMarquee className="w-full max-w-xl">
<p className="p-4 whitespace-nowrap">
FREELANCE DEVELOPER
<span className="inline-block">
<ArrowUpRight />
</span>
</p>
<p className="p-4 whitespace-nowrap">
FREELANCE DEVELOPER
<span className="inline-block">
<ArrowUpRight />
</span>
</p>
<p className="p-4 whitespace-nowrap">
FREELANCE DEVELOPER
<span className="inline-block">
<ArrowUpRight />
</span>
</p>
</InfiniteMarquee>
FREELANCE DEVELOPER
FREELANCE DEVELOPER
FREELANCE DEVELOPER