Skip to main content

Marquee

The Marquee component creates an infinite scrolling effect perfect for displaying logos, testimonials, or any content that needs continuous horizontal movement. Features smooth CSS animations with pause-on-hover support.

Installation

npm install @craftdotui/components

Import

import Marquee from "@craftdotui/components";

Usage

import Marquee from "@craftdotui/components";

export default function Example() {
  return (
    <Marquee>
      <div className="flex gap-8">
        <span className="text-2xl font-bold">Item 1</span>
        <span className="text-2xl font-bold">Item 2</span>
        <span className="text-2xl font-bold">Item 3</span>
        <span className="text-2xl font-bold">Item 4</span>
      </div>
    </Marquee>
  );
}

Props

children
React.ReactNode
required
The content to scroll. Typically a flex container with items.
duration
number
default:"20"
Animation duration in seconds. Lower values = faster scrolling.
repeat
number
default:"2"
Number of times to repeat the content. Minimum 2 recommended for seamless loops.
direction
'left' | 'right'
default:"'left'"
Scroll direction.
pauseOnHover
boolean
default:"true"
Whether to pause animation when hovering.
gap
number
default:"0"
Gap between repeated content instances in pixels.
className
string
Additional CSS classes for the container.

Animation Details

CSS Keyframes

The component uses pure CSS animations for optimal performance:
@keyframes marquee-left {
  0% { transform: translateX(0); }
  100% { transform: translateX(-100%); }
}

@keyframes marquee-right {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(0); }
}

Animation Properties

animation: `marquee-${direction} ${duration}s linear infinite`
  • Timing: linear for constant speed
  • Iteration: infinite for continuous scrolling
  • Duration: Configurable via props
The repeat prop duplicates the content to ensure seamless infinite scrolling without gaps.

Examples

Partner Logos

import Marquee from "@craftdotui/components";

export default function PartnerLogos() {
  const partners = [
    { name: "Google", logo: "/partners/google.svg" },
    { name: "Microsoft", logo: "/partners/microsoft.svg" },
    { name: "Apple", logo: "/partners/apple.svg" },
    { name: "Amazon", logo: "/partners/amazon.svg" },
    { name: "Meta", logo: "/partners/meta.svg" },
  ];

  return (
    <div className="py-12 bg-gray-50">
      <h2 className="text-center text-2xl font-bold mb-8">Trusted by industry leaders</h2>
      <Marquee duration={40} gap={64} className="py-4">
        {partners.map((partner, i) => (
          <img
            key={i}
            src={partner.logo}
            alt={partner.name}
            className="h-16 w-auto opacity-60 hover:opacity-100 transition-opacity"
          />
        ))}
      </Marquee>
    </div>
  );
}

Testimonials Scroll

import Marquee from "@craftdotui/components";
import { Star } from "lucide-react";

export default function Testimonials() {
  const testimonials = [
    { text: "Amazing product!", author: "John Doe" },
    { text: "Best service ever!", author: "Jane Smith" },
    { text: "Highly recommended!", author: "Bob Johnson" },
  ];

  return (
    <Marquee duration={50} gap={32}>
      {testimonials.map((testimonial, i) => (
        <div key={i} className="bg-white p-6 rounded-lg shadow-md min-w-[300px]">
          <div className="flex gap-1 mb-3">
            {[...Array(5)].map((_, i) => (
              <Star key={i} className="w-4 h-4 fill-yellow-400 text-yellow-400" />
            ))}
          </div>
          <p className="text-gray-700 mb-2">"{testimonial.text}"</p>
          <p className="text-sm text-gray-500">- {testimonial.author}</p>
        </div>
      ))}
    </Marquee>
  );
}

Dual Direction Marquees

import Marquee from "@craftdotui/components";

export default function DualMarquee() {
  const skills = [
    "React", "TypeScript", "Next.js", "Tailwind CSS", 
    "Node.js", "GraphQL", "PostgreSQL", "Docker"
  ];

  return (
    <div className="space-y-4">
      <Marquee direction="left" duration={30}>
        {skills.map((skill, i) => (
          <div key={i} className="px-6 py-3 bg-gradient-to-r from-blue-500 to-purple-500 text-white rounded-full font-semibold">
            {skill}
          </div>
        ))}
      </Marquee>
      
      <Marquee direction="right" duration={35}>
        {skills.reverse().map((skill, i) => (
          <div key={i} className="px-6 py-3 bg-gradient-to-r from-pink-500 to-orange-500 text-white rounded-full font-semibold">
            {skill}
          </div>
        ))}
      </Marquee>
    </div>
  );
}

News Ticker

import Marquee from "@craftdotui/components";

export default function NewsTicker() {
  const news = [
    "Breaking: New feature released!",
    "Update: Server maintenance scheduled for tonight",
    "Announcement: Join our webinar next week",
  ];

  return (
    <div className="bg-black text-white py-2">
      <Marquee duration={25} pauseOnHover={true}>
        {news.map((item, i) => (
          <span key={i} className="mx-8">
            <span className="text-red-500 mr-2"></span>
            {item}
          </span>
        ))}
      </Marquee>
    </div>
  );
}
For seamless scrolling, ensure your content width is sufficient. Use repeat={2} or higher to avoid visible gaps.

Best Practices

Performance

  • Uses CSS animations (GPU-accelerated)
  • No JavaScript required for animation loop
  • Minimal re-renders

Content Guidelines

  • Keep individual items similar in size for visual consistency
  • Use fixed widths for items when possible
  • Include enough items to fill the viewport width
  • Set appropriate gap values to prevent crowding

Speed Configuration

// Slow, elegant scroll
<Marquee duration={60}>

// Medium speed (default)
<Marquee duration={20}>

// Fast ticker
<Marquee duration={10}>

Accessibility

Continuous motion can be problematic for users with vestibular disorders. Consider:
  • Setting pauseOnHover={true} (default)
  • Providing a pause/play control
  • Respecting prefers-reduced-motion media query

Use Cases

  • Logo showcases
  • Partner/sponsor displays
  • Testimonial carousels
  • News tickers
  • Social media feeds
  • Product highlights
  • Award badges
  • Technology stack displays

Build docs developers (and LLMs) love