Marquee
Also called infinite marquee, logo ticker, or scrolling logos
A strip of logos or text that scrolls sideways in an endless loop, often used for "trusted by" rows and announcements.
import { useRef } from 'react';
import {
motion,
useAnimationFrame,
useMotionValue,
useReducedMotion
} from 'motion/react';
const SPEED = 40; // px per second, steady and linear
type Logo = { name: string; src: string };
export function LogoMarquee({ logos }: { logos: Logo[] }) {
const track = useRef<HTMLDivElement>(null);
const paused = useRef(false);
const x = useMotionValue(0);
const reduceMotion = useReducedMotion();
useAnimationFrame((_, delta) => {
if (reduceMotion || paused.current || !track.current) return;
// Slide by exactly one copy, then wrap; the second copy hides the jump.
const copyWidth = track.current.scrollWidth / 2;
x.set((x.get() - (SPEED * delta) / 1000) % copyWidth);
});
return (
<div
onPointerEnter={() => (paused.current = true)}
onPointerLeave={() => (paused.current = false)}
className='overflow-hidden [mask-image:linear-gradient(to_right,transparent,black_15%,black_85%,transparent)]'
>
<motion.div ref={track} style={{ x }} className='flex w-max'>
{[false, true].map((duplicate) => (
// pr-12 matches gap-12, so both copies are exactly the same width.
<ul
key={String(duplicate)}
aria-hidden={duplicate || undefined}
className='flex shrink-0 items-center gap-12 pr-12'
>
{logos.map((logo) => (
<li key={logo.name}>
<img
src={logo.src}
alt={duplicate ? '' : logo.name}
className='h-7 w-auto opacity-60 grayscale'
/>
</li>
))}
</ul>
))}
</motion.div>
</div>
);
}Add a logo marquee under the hero: one row of 8 grayscale customer logos that scrolls left in an endless loop at about 40px per second with linear timing. Duplicate the row for a seamless loop, fade both edges with a mask over the outer 15%, pause on hover, hide the duplicate from screen readers, and show a still row when prefers-reduced-motion is set.
Paste into Layerwise or any AI coding tool.
What is Marquee?
A marquee moves a row of content, usually customer logos, testimonials, or short announcements, sideways at a steady speed. When the last item leaves, the first one is already coming back, so the strip never ends. The trick is two identical copies of the row side by side: the track slides left by exactly one copy, then jumps back to the start, and the jump is invisible because the second copy now sits where the first began.
Use it for social proof under a hero, a row of integrations, or a ticker of updates. Keep it slow, around 30 to 60px per second, with linear timing so it never speeds up or stalls. A soft fade at both edges, made with mask-image, hides where items enter and leave.
Pause it on hover so people can read an item, and stop it under prefers-reduced-motion. Hide the duplicate copy from screen readers with aria-hidden so the list is read once. The old HTML <marquee> tag is obsolete; build it with CSS.
Often confused with
- Carousel
- A carousel shows one slide at a time and moves when the user or a timer advances it. A marquee scrolls continuously on its own.
Related terms
All termsCarousel
A row of slides shown one at a time and moved with arrows, dots, swipes, or a timer, to fit several images or cards in one spot.
Looping animation
An animation that plays more than once, either a set number of times or forever, set in CSS with animation-iteration-count.
Linear easing
Easing that moves at one constant speed from start to finish, with no speeding up or slowing down, drawn as a straight line on a graph.
Mask
A CSS technique that uses an image or gradient to set how visible each part of an element is, often used to fade edges softly.
Build it with Layerwise
Describe your app, watch it run in a live preview, and publish it with a database, storage, and sign-in built in.