# Logos Two Row Opposing Marquee — React Logo Cloud

> Two rows of logo chips glide in opposite directions; page scroll pushes them further apart in each direction, so the rows shear as you move.

- Category: [Logo Clouds](https://pixelpapa.com/components/logo-clouds.md)
- Tags: logos, marquee, scroll, chips, social-proof
- Dependencies: motion (plus React and Tailwind CSS v4)
- Last updated: 2026-11-13
- Live preview: https://pixelpapa.com/components/logo-clouds/logos-two-row-opposing-marquee

## Install

```bash
npx shadcn@latest add "https://pixelpapa.com/r/logos-two-row-opposing-marquee.json"
```

The file is written to `components/pixelpapa/logos-two-row-opposing-marquee.tsx`. To install manually, run `npm install motion` and copy the source below into your project. It imports `cn` from `@/lib/utils`, which every shadcn project has.

## Source

```tsx
"use client";

import { motion, useScroll, useSpring, useTransform } from "motion/react";
import { useRef } from "react";
import { cn } from "@/lib/utils";

type Logo = { name: string; d: string; cls: string };

// Fictional wordmarks: one 24px glyph path plus a type treatment each.
const logos: Logo[] = [
  { name: "Alderwood", d: "M12 3 22 21H2Z", cls: "font-semibold tracking-tight" },
  { name: "Kestrel", d: "M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm0 5a5 5 0 1 1 0 10 5 5 0 0 1 0-10Z", cls: "font-serif text-[1.15em] italic" },
  { name: "TIDELINE", d: "M3 3h12v12H3Zm6 6h12v12H9Z", cls: "text-[0.82em] font-bold tracking-[0.18em]" },
  { name: "basalt", d: "M12 2 22 12 12 22 2 12Z M12 7 7 12l5 5 5-5Z", cls: "font-mono font-medium" },
  { name: "Halden", d: "M3 14h4v7H3Zm7-6h4v13h-4Zm7-5h4v18h-4Z", cls: "font-bold tracking-tighter" },
  { name: "Larkspur", d: "M12 12V2a10 10 0 0 1 10 10Zm0 0v10A10 10 0 0 1 2 12Z", cls: "font-serif text-[1.1em]" },
  { name: "ARCLIGHT", d: "M2 17a10 10 0 0 1 20 0h-5a5 5 0 0 0-10 0Z", cls: "text-[0.82em] font-medium tracking-[0.3em]" },
  { name: "Fieldstone", d: "M12 2l8.66 5v10L12 22l-8.66-5V7Z", cls: "font-medium" },
  { name: "wexford", d: "M9 2h6v7h7v6h-7v7H9v-7H2V9h7Z", cls: "font-semibold tracking-tight" },
  { name: "Marlowe", d: "M8 5a7 7 0 1 0 0 14A7 7 0 0 0 8 5Zm8 0a7 7 0 1 1 0 14 7 7 0 0 1 0-14Z", cls: "font-serif text-[1.15em] italic" },
];

function Wordmark({ logo, className }: { logo: Logo; className?: string }) {
  return (
    <span className={cn("inline-flex items-center gap-2.5 text-xl whitespace-nowrap", className)}>
      <svg viewBox="0 0 24 24" fill="currentColor" fillRule="evenodd" aria-hidden className="size-[1.2em] shrink-0">
        <path d={logo.d} />
      </svg>
      <span className={logo.cls}>{logo.name}</span>
    </span>
  );
}

function Row({ items, reverse, duration }: { items: Logo[]; reverse?: boolean; duration: number }) {
  return (
    <div
      className="flex w-max motion-reduce:[animation-play-state:paused]"
      style={{ animation: `pp-logos-two-row-opposing-marquee-slide ${duration}s linear infinite ${reverse ? "reverse" : "normal"}` }}
    >
      {[0, 1].map((copy) => (
        <ul key={copy} aria-hidden={copy === 1} className="flex shrink-0">
          {items.map((logo) => (
            <li key={logo.name} className="pr-4">
              <span className="flex h-16 items-center rounded-2xl border border-border bg-card px-7 shadow-sm">
                <Wordmark logo={logo} className="text-foreground/80" />
              </span>
            </li>
          ))}
        </ul>
      ))}
    </div>
  );
}

export default function LogosTwoRowOpposingMarquee() {
  const ref = useRef<HTMLElement>(null);
  const { scrollYProgress } = useScroll({ target: ref, offset: ["start end", "end start"] });
  const eased = useSpring(scrollYProgress, { stiffness: 120, damping: 30 });
  const left = useTransform(eased, [0, 1], [60, -180]);
  const right = useTransform(eased, [0, 1], [-180, 60]);

  return (
    <section ref={ref} className="w-full overflow-hidden bg-background py-20 sm:py-24">
      <style>{`@keyframes pp-logos-two-row-opposing-marquee-slide { to { transform: translateX(-50%); } }`}</style>
      <div className="mx-auto max-w-2xl px-6 text-center">
        <h2 className="text-3xl font-semibold tracking-tight text-balance text-foreground sm:text-4xl">
          In good company, in every direction
        </h2>
        <p className="mt-3 text-muted-foreground">Logistics, fintech, health and climate teams run on Harbor every day.</p>
      </div>
      <div className="mt-12 space-y-4 [mask-image:linear-gradient(to_right,transparent,black_12%,black_88%,transparent)]">
        <motion.div style={{ x: left }}>
          <Row items={logos} duration={46} />
        </motion.div>
        <motion.div style={{ x: right }}>
          <Row items={[...logos.slice(5), ...logos.slice(0, 5)]} duration={52} reverse />
        </motion.div>
      </div>
    </section>
  );
}
```

## AI prompt

```text
Add the "Logos Two Row Opposing Marquee" component from PixelPapa UI to this project.

What it is: Two rows of logo chips glide in opposite directions; page scroll pushes them further apart in each direction, so the rows shear as you move.
Category: Logo Clouds. Depends on: motion.

1. Install it with the shadcn CLI:
   npx shadcn@latest add "https://pixelpapa.com/r/logos-two-row-opposing-marquee.json"
   (If the CLI is unavailable, fetch that URL, write files[0].content to components/pixelpapa/logos-two-row-opposing-marquee.tsx and install the listed dependencies.)
2. Import it from "@/components/pixelpapa/logos-two-row-opposing-marquee" and place it where I describe below.
3. Keep its animation timings and accessibility attributes. Replace the demo copy and data with content that fits my product, and use my existing theme tokens (bg-background, text-foreground, bg-primary, border-border) rather than hard-coded colours.

Where to use it: <describe the page and position here>
```

## More logo clouds

- [Logos Grid Hover Reveal](https://pixelpapa.com/components/logo-clouds/logos-grid-hover-reveal.md) (Pro): A bordered logo grid where each cell rolls its wordmark up and away on hover or focus to reveal that customer's headline result and a case-study link.
- [Logos Marquee Fade](https://pixelpapa.com/components/logo-clouds/logos-marquee-fade.md): A single row of wordmarks drifting left forever, masked to fade at both edges; hovering slows the belt and lifts the logo under the cursor.
- [Logos Orbit Ring](https://pixelpapa.com/components/logo-clouds/logos-orbit-ring.md): Logo chips ride two counter-rotating rings that rise over the horizon behind the headline; each chip counter-spins so its wordmark stays upright.
- [Logos Spotlight Swap](https://pixelpapa.com/components/logo-clouds/logos-spotlight-swap.md) (Pro): Six fixed cells that take turns swapping their wordmark: every couple of seconds one cell blurs out its logo and focuses a new one from the pool.
- [Logos With Stat Header](https://pixelpapa.com/components/logo-clouds/logos-with-stat-header.md) (Pro): A logo strip led by a counting headline figure; the stat counts up on view, then the wordmarks rise in one by one along a hairline rule.
