Retour au catalogue

Marquee Dual Speed

Deux rangees de marquee a vitesses et directions differentes creant un effet de profondeur visuelle.

marqueemedium Both Responsive a11y
boldplayfuluniversalagencyeventstacked
Theme
"use client";

import { motion } from "framer-motion";

interface MarqueeDualSpeedProps {
  topItems?: string[];
  bottomItems?: string[];
  topSpeed?: number;
  bottomSpeed?: number;
}

function MarqueeRow({
  items,
  speed,
  reverse = false,
  style,
}: {
  items: string[];
  speed: number;
  reverse?: boolean;
  style?: React.CSSProperties;
}) {
  const doubled = [...items, ...items];

  return (
    <div style={{ overflow: "hidden", ...style }}>
      <motion.div
        animate={{ x: reverse ? ["-50%", "0%"] : ["0%", "-50%"] }}
        transition={{ duration: speed, ease: "linear", repeat: Infinity }}
        style={{ display: "flex", whiteSpace: "nowrap" }}
      >
        {doubled.map((item, i) => (
          <span
            key={`${item}-${i}`}
            style={{
              display: "inline-flex",
              alignItems: "center",
              flexShrink: 0,
              paddingRight: "2.5rem",
              fontSize: "clamp(1.25rem, 3vw, 2.5rem)",
              fontWeight: 800,
              letterSpacing: "-0.02em",
              textTransform: "uppercase",
              color: "var(--color-foreground)",
            }}
          >
            {item}
          </span>
        ))}
      </motion.div>
    </div>
  );
}

export default function MarqueeDualSpeed({
  topItems = [],
  bottomItems = [],
  topSpeed = 25,
  bottomSpeed = 35,
}: MarqueeDualSpeedProps) {
  if (topItems.length === 0 && bottomItems.length === 0) return null;

  return (
    <section
      style={{
        padding: "2rem 0",
        background: "var(--color-background)",
        overflow: "hidden",
      }}
    >
      {topItems.length > 0 && (
        <MarqueeRow
          items={topItems}
          speed={topSpeed}
          style={{ marginBottom: "0.75rem" }}
        />
      )}
      {bottomItems.length > 0 && (
        <MarqueeRow
          items={bottomItems}
          speed={bottomSpeed}
          reverse
          style={{
            opacity: 0.35,
          }}
        />
      )}
    </section>
  );
}

Avis

Marquee Dual Speed — React Marquee Section — Incubator