Marquee Effect
The marquee component is designed to create a dynamic user experience by continuously scrolling text horizontally. This effect is perfect for highlighting important information, announcements, or news headlines that need to catch the user's attention. The smooth scrolling animation adds movement and liveliness to the interface, making important content more noticeable to users. This example was created using Tailwind CSS and Framer Motion.
Examples
Bundui ComponentsBundui ComponentsBundui ComponentsBundui Components
Reverse routing
Bundui ComponentsBundui ComponentsBundui ComponentsBundui Components
Bundui ComponentsBundui ComponentsBundui ComponentsBundui Components
Install the following dependencies:
npm i framer-motion clsx tailwind-merge @motionone/utils
Add util file
import { ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
Copy and paste the following code into your project.
"use client";
import { useRef } from "react";
import {
motion,
useScroll,
useSpring,
useTransform,
useMotionValue,
useVelocity,
useAnimationFrame,
} from "framer-motion";
import { wrap } from "@motionone/utils";
import { cn } from "@/lib/utils";
type MarqueeAnimationProps = {
children: string;
className?: string;
direction?: "left" | "right";
baseVelocity: number;
};
export default function MarqueeAnimation({
children,
className,
direction = "left",
baseVelocity = 10,
}: MarqueeAnimationProps) {
const baseX = useMotionValue(0);
const { scrollY } = useScroll();
const scrollVelocity = useVelocity(scrollY);
const smoothVelocity = useSpring(scrollVelocity, {
damping: 50,
stiffness: 400,
});
const velocityFactor = useTransform(smoothVelocity, [0, 1000], [0, 0], {
clamp: false,
});
const x = useTransform(baseX, (v) => `${wrap(-20, -45, v)}%`);
const directionFactor = useRef<number>(1);
useAnimationFrame((t, delta) => {
let moveBy = directionFactor.current * baseVelocity * (delta / 1000);
if (direction == "left") {
directionFactor.current = 1;
} else if (direction == "right") {
directionFactor.current = -1;
}
moveBy += directionFactor.current * moveBy * velocityFactor.get();
baseX.set(baseX.get() + moveBy);
});
return (
<div className="overflow-hidden max-w-[100vw] text-nowrap flex-nowrap flex relative">
<motion.div
className={cn(
"font-bold uppercase text-5xl flex flex-nowrap text-nowrap *:block *:me-10",
className
)}
style={{ x }}
>
<span>{children}</span>
<span>{children}</span>
<span>{children}</span>
<span>{children}</span>
</motion.div>
</div>
);
}
Usage
import MarqueeEffect from "@/components/ui/marquee-effect";
export default function MarqueeEffectExample() {
return <MarqueeEffect baseVelocity={-3}>Bundui Components</MarqueeEffect>;
}