Marquee — <mv-marquee>

Infinite scroll of logos, testimonials or cards: speed in px/s regardless of content size, horizontal or vertical, drag with inertia, edge fade and a tilted 3D variant.

CategoryLayout
TypeWeb Component (<mv-marquee>)
Statusstable
Keywordsmarquee, logos, testimonials, infinite-scroll, ticker, 3d, draggable

When to use

Avoid when

Install

node scripts/add.mjs marquee --out ./src/marvelous

AI agent with the Marvelous UI MCP server: install_components({ slugs: ["marquee"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Files copied (dependencies included): tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/motion.js, core/observe.js, components/marquee/marquee.js, components/marquee/marquee.css.

Usage

Canonical markup — start from it and customize with attributes, data-* and CSS variables:

<div class="mq-demo" id="mq-demo">
  <style>
    #mq-demo { width: 100%; display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.75rem; }
    #mq-demo .mq-label { margin: 0 0 .6rem; text-align: center; font-size: .75rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--mv-fg-subtle); }
    #mq-demo .mq-logo { height: 28px; width: auto; color: var(--mv-fg-muted); opacity: .8; transition: opacity .2s, color .2s; }
    #mq-demo .mq-logo:hover { opacity: 1; color: var(--mv-fg); }
    #mq-demo .mq-quote { width: 19rem; margin: 0; padding: 1.1rem 1.2rem; gap: .9rem; user-select: none; }
    #mq-demo .mq-quote blockquote { margin: 0; font-size: .875rem; line-height: 1.5; }
    #mq-demo .mq-quote figcaption { display: flex; align-items: center; gap: .65rem; font-size: .8125rem; }
    #mq-demo .mq-quote figcaption > span:last-child { display: grid; line-height: 1.3; }
    #mq-demo .mq-quote small { color: var(--mv-fg-muted); font-size: .75rem; }
    #mq-demo .mq-avatar { display: grid; place-items: center; width: 2.1rem; height: 2.1rem; border-radius: 50%; font-size: .75rem; font-weight: 700; color: #fff; background: linear-gradient(135deg, oklch(0.72 0.16 var(--hue)), oklch(0.5 0.2 calc(var(--hue) + 40))); }
    #mq-demo .mq-bottom { display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); gap: 1.25rem; align-items: stretch; }
    #mq-demo .mq-review { padding: .8rem .95rem; border: 1px solid var(--mv-border); border-radius: var(--mv-radius-lg); background: var(--mv-surface); box-shadow: var(--mv-shadow-xs); font-size: .8125rem; }
    #mq-demo .mq-review p { margin: .25rem 0 .2rem; line-height: 1.4; }
    #mq-demo .mq-review small { color: var(--mv-fg-muted); }
    #mq-demo .mq-stars { color: var(--mv-warning); letter-spacing: 1px; font-size: .75rem; }
    #mq-demo .mq3 { background: var(--mv-bg-muted); border: 1px solid var(--mv-border); }
    #mq-demo .mq3-tile { aspect-ratio: 4 / 3; border-radius: var(--mv-radius-lg); background: linear-gradient(145deg, oklch(0.74 0.15 var(--hue)), oklch(0.52 0.2 calc(var(--hue) + 35))); overflow: hidden; }
    #mq-demo .mq3-tile svg { width: 100%; height: 100%; }
    @media (max-width: 640px) { #mq-demo .mq-bottom { grid-template-columns: 1fr; } #mq-demo .mq-bottom > mv-marquee[vertical] { display: none; } }
  </style>

  <section aria-labelledby="mq-demo-logos">
    <p class="mq-label" id="mq-demo-logos">Trusted by</p>
    <mv-marquee speed="36" fade pause-on-hover style="--mv-marquee-gap: 3rem">
      <svg class="mq-logo" viewBox="0 0 92 32" height="28" role="img" aria-label="Lumen" fill="currentColor"><circle cx="13" cy="16" r="6"/><path d="M13 3v4M13 25v4M0 16h4M22 16h4M4 7l3 3M19 22l3 3M4 25l3-3M19 10l3-3" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" fill="none"/><text x="33" y="23" font-size="19" font-weight="700" letter-spacing="-0.6">Lumen</text></svg><svg class="mq-logo" viewBox="0 0 103 32" height="28" role="img" aria-label="Nordik" fill="currentColor"><path d="M1 26 10 8l5 9 3-5 8 14z"/><text x="33" y="23" font-size="19" font-weight="700" letter-spacing="-0.6">Nordik</text></svg><svg class="mq-logo" viewBox="0 0 114 32" height="28" role="img" aria-label="Arcadia" fill="currentColor"><path d="M3 26a10 10 0 0 1 20 0" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round"/><circle cx="13" cy="10" r="3"/><text x="33" y="23" font-size="19" font-weight="700" letter-spacing="-0.6">Arcadia</text></svg><svg class="mq-logo" viewBox="0 0 114 32" height="28" role="img" aria-label="Polaris" fill="currentColor"><path d="M13 2c1 8 3 11 11 14-8 3-10 6-11 14-1-8-3-11-11-14 8-3 10-6 11-14z"/><text x="33" y="23" font-size="19" font-weight="700" letter-spacing="-0.6">Polaris</text></svg><svg class="mq-logo" viewBox="0 0 103 32" height="28" role="img" aria-label="Vertex" fill="currentColor"><path d="M13 3 24 9.5v13L13 29 2 22.5v-13z" fill="none" stroke="currentColor" stroke-width="3" stroke-linejoin="round"/><circle cx="13" cy="16" r="3.5"/><text x="33" y="23" font-size="19" font-weight="700" letter-spacing="-0.6">Vertex</text></svg><svg class="mq-logo" viewBox="0 0 103 32" height="28" role="img" aria-label="Octave" fill="currentColor"><circle cx="9" cy="16" r="7" fill="none" stroke="currentColor" stroke-width="3"/><circle cx="18" cy="16" r="7"/><text x="33" y="23" font-size="19" font-weight="700" letter-spacing="-0.6">Octave</text></svg><svg class="mq-logo" viewBox="0 0 103 32" height="28" role="img" aria-label="Kairos" fill="currentColor"><path d="M4 4h18L13 16l9 12H4l9-12z" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linejoin="round"/><path d="M8 26h10l-5-6z"/><text x="33" y="23" font-size="19" font-weight="700" letter-spacing="-0.6">Kairos</text></svg><svg class="mq-logo" viewBox="0 0 114 32" height="28" role="img" aria-label="Stellar" fill="currentColor"><path d="M1 12c4-4 8-4 12 0s8 4 12 0M1 20c4-4 8-4 12 0s8 4 12 0" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"/><text x="33" y="23" font-size="19" font-weight="700" letter-spacing="-0.6">Stellar</text></svg>
    </mv-marquee>
  </section>

  <mv-marquee speed="28" fade pause-on-hover drag aria-label="Customer testimonials" style="--mv-marquee-padding: .5rem; --mv-marquee-fade: 8%; --mv-marquee-align: stretch">
    <figure class="mv-card mq-quote">
      <blockquote>“We replaced three animation libraries with Marvelous. Our bundle shrank by 180 KB.”</blockquote>
      <figcaption><span class="mq-avatar" style="--hue:280" aria-hidden="true">LM</span><span><strong>Leah Morgan</strong><small>CTO · Nordik</small></span></figcaption>
    </figure>
    <figure class="mv-card mq-quote">
      <blockquote>“The same components run in our Vue app and our Astro site without a single line of glue code.”</blockquote>
      <figcaption><span class="mq-avatar" style="--hue:200" aria-hidden="true">YB</span><span><strong>Yara Bishop</strong><small>Frontend lead · Arcadia</small></span></figcaption>
    </figure>
    <figure class="mv-card mq-quote">
      <blockquote>“Focus, keyboard, reduced motion: accessibility is taken seriously. That’s rare.”</blockquote>
      <figcaption><span class="mq-avatar" style="--hue:330" aria-hidden="true">CR</span><span><strong>Chloe Reed</strong><small>Design system · Polaris</small></span></figcaption>
    </figure>
    <figure class="mv-card mq-quote">
      <blockquote>“The dock and the marquee blew our board away in the demo. And it’s plain HTML.”</blockquote>
      <figcaption><span class="mq-avatar" style="--hue:30" aria-hidden="true">HL</span><span><strong>Hana Lee</strong><small>Founder · Kairos</small></span></figcaption>
    </figure>
    <figure class="mv-card mq-quote">
      <blockquote>“Finally, animations that respect prefers-reduced-motion without us having to think about it.”</blockquote>
      <figcaption><span class="mq-avatar" style="--hue:150" aria-hidden="true">IG</span><span><strong>Isabel Garcia</strong><small>Accessibility engineer · Stellar</small></span></figcaption>
    </figure>
    <figure class="mv-card mq-quote">
      <blockquote>“Integrated into our Angular back office in one afternoon. The product team is thrilled.”</blockquote>
      <figcaption><span class="mq-avatar" style="--hue:90" aria-hidden="true">TN</span><span><strong>Thomas Nguyen</strong><small>Staff engineer · Vertex</small></span></figcaption>
    </figure>
  </mv-marquee>

  <div class="mq-bottom">
    <mv-marquee vertical reverse speed="22" fade pause-on-hover aria-label="Reviews" style="--mv-marquee-height: 20rem; --mv-marquee-gap: .75rem">
      <div class="mq-review"><span class="mq-stars" role="img" aria-label="5 out of 5">★★★★★</span><p>Up and running in 2 minutes flat.</p><small>— Maya</small></div>
      <div class="mq-review"><span class="mq-stars" role="img" aria-label="5 out of 5">★★★★★</span><p>The most beautiful web dock I’ve ever seen.</p><small>— Kenji</small></div>
      <div class="mq-review"><span class="mq-stars" role="img" aria-label="5 out of 5">★★★★★</span><p>Zero dependencies, zero headaches.</p><small>— Julia</small></div>
      <div class="mq-review"><span class="mq-stars" role="img" aria-label="4 out of 5">★★★★☆</span><p>Works perfectly with Tailwind and cascade layers.</p><small>— Aaron</small></div>
      <div class="mq-review"><span class="mq-stars" role="img" aria-label="5 out of 5">★★★★★</span><p>Dark mode is flawless.</p><small>— Sarah</small></div>
      <div class="mq-review"><span class="mq-stars" role="img" aria-label="5 out of 5">★★★★★</span><p>Clear docs, clean API.</p><small>— Nathan</small></div>
    </mv-marquee>
    <mv-marquee class="mq3" data-variant="3d" columns="5" speed="18" aria-hidden="true" style="--mv-marquee-height: 20rem">
      <div class="mq3-tile" style="--hue:280"><svg viewBox="0 0 160 120"><rect x="14" y="14" width="60" height="7" rx="3.5" fill="#fff" opacity=".9"/><rect x="14" y="26" width="38" height="5" rx="2.5" fill="#fff" opacity=".5"/><g fill="#fff" opacity=".85"><rect x="18" y="78" width="14" height="26" rx="3"/><rect x="40" y="62" width="14" height="42" rx="3"/><rect x="62" y="70" width="14" height="34" rx="3"/><rect x="84" y="50" width="14" height="54" rx="3"/><rect x="106" y="40" width="14" height="64" rx="3"/><rect x="128" y="56" width="14" height="48" rx="3"/></g></svg></div>
      <div class="mq3-tile" style="--hue:250"><svg viewBox="0 0 160 120"><rect x="14" y="14" width="56" height="8" rx="4" fill="#fff" opacity=".9"/><rect x="14" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="71" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="33" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="128" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="90" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="52" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/></svg></div>
      <div class="mq3-tile" style="--hue:20"><svg viewBox="0 0 160 120"><rect x="14" y="16" width="92" height="24" rx="12" fill="#fff" opacity=".9"/><rect x="54" y="48" width="92" height="24" rx="12" fill="#fff" opacity=".45"/><rect x="14" y="80" width="70" height="24" rx="12" fill="#fff" opacity=".9"/></svg></div>
      <div class="mq3-tile" style="--hue:160"><svg viewBox="0 0 160 120"><rect x="14" y="14" width="44" height="7" rx="3.5" fill="#fff" opacity=".9"/><text x="14" y="50" font-size="22" font-weight="700" fill="#fff">+38%</text><path d="M14 100c16-4 22-24 38-22s22 14 36 4 20-30 36-32 16 6 22 4" fill="none" stroke="#fff" stroke-width="4" stroke-linecap="round" opacity=".9"/></svg></div>
      <div class="mq3-tile" style="--hue:320"><svg viewBox="0 0 160 120"><circle cx="118" cy="34" r="14" fill="#fff" opacity=".85"/><path d="M0 120V92l34-30 26 22 30-36 70 72z" fill="#fff" opacity=".35"/><path d="M0 120v-14l40-26 40 24 36-20 44 36z" fill="#fff" opacity=".6"/></svg></div>
      <div class="mq3-tile" style="--hue:200"><svg viewBox="0 0 160 120"><circle cx="40" cy="44" r="20" fill="#fff" opacity=".9"/><rect x="70" y="32" width="70" height="8" rx="4" fill="#fff" opacity=".9"/><rect x="70" y="48" width="48" height="6" rx="3" fill="#fff" opacity=".55"/><rect x="16" y="80" width="128" height="26" rx="8" fill="#fff" opacity=".25"/><rect x="26" y="89" width="60" height="8" rx="4" fill="#fff" opacity=".8"/></svg></div>
      <div class="mq3-tile" style="--hue:60"><svg viewBox="0 0 160 120"><rect x="14" y="14" width="60" height="7" rx="3.5" fill="#fff" opacity=".9"/><rect x="14" y="26" width="38" height="5" rx="2.5" fill="#fff" opacity=".5"/><g fill="#fff" opacity=".85"><rect x="18" y="78" width="14" height="26" rx="3"/><rect x="40" y="62" width="14" height="42" rx="3"/><rect x="62" y="70" width="14" height="34" rx="3"/><rect x="84" y="50" width="14" height="54" rx="3"/><rect x="106" y="40" width="14" height="64" rx="3"/><rect x="128" y="56" width="14" height="48" rx="3"/></g></svg></div>
      <div class="mq3-tile" style="--hue:300"><svg viewBox="0 0 160 120"><rect x="14" y="14" width="56" height="8" rx="4" fill="#fff" opacity=".9"/><rect x="14" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="71" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="33" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="128" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="90" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="52" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/></svg></div>
      <div class="mq3-tile" style="--hue:280"><svg viewBox="0 0 160 120"><rect x="14" y="16" width="92" height="24" rx="12" fill="#fff" opacity=".9"/><rect x="54" y="48" width="92" height="24" rx="12" fill="#fff" opacity=".45"/><rect x="14" y="80" width="70" height="24" rx="12" fill="#fff" opacity=".9"/></svg></div>
      <div class="mq3-tile" style="--hue:250"><svg viewBox="0 0 160 120"><rect x="14" y="14" width="44" height="7" rx="3.5" fill="#fff" opacity=".9"/><text x="14" y="50" font-size="22" font-weight="700" fill="#fff">+38%</text><path d="M14 100c16-4 22-24 38-22s22 14 36 4 20-30 36-32 16 6 22 4" fill="none" stroke="#fff" stroke-width="4" stroke-linecap="round" opacity=".9"/></svg></div>
      <div class="mq3-tile" style="--hue:20"><svg viewBox="0 0 160 120"><circle cx="118" cy="34" r="14" fill="#fff" opacity=".85"/><path d="M0 120V92l34-30 26 22 30-36 70 72z" fill="#fff" opacity=".35"/><path d="M0 120v-14l40-26 40 24 36-20 44 36z" fill="#fff" opacity=".6"/></svg></div>
      <div class="mq3-tile" style="--hue:160"><svg viewBox="0 0 160 120"><circle cx="40" cy="44" r="20" fill="#fff" opacity=".9"/><rect x="70" y="32" width="70" height="8" rx="4" fill="#fff" opacity=".9"/><rect x="70" y="48" width="48" height="6" rx="3" fill="#fff" opacity=".55"/><rect x="16" y="80" width="128" height="26" rx="8" fill="#fff" opacity=".25"/><rect x="26" y="89" width="60" height="8" rx="4" fill="#fff" opacity=".8"/></svg></div>
      <div class="mq3-tile" style="--hue:320"><svg viewBox="0 0 160 120"><rect x="14" y="14" width="60" height="7" rx="3.5" fill="#fff" opacity=".9"/><rect x="14" y="26" width="38" height="5" rx="2.5" fill="#fff" opacity=".5"/><g fill="#fff" opacity=".85"><rect x="18" y="78" width="14" height="26" rx="3"/><rect x="40" y="62" width="14" height="42" rx="3"/><rect x="62" y="70" width="14" height="34" rx="3"/><rect x="84" y="50" width="14" height="54" rx="3"/><rect x="106" y="40" width="14" height="64" rx="3"/><rect x="128" y="56" width="14" height="48" rx="3"/></g></svg></div>
      <div class="mq3-tile" style="--hue:200"><svg viewBox="0 0 160 120"><rect x="14" y="14" width="56" height="8" rx="4" fill="#fff" opacity=".9"/><rect x="14" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="71" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="33" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="128" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="90" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="52" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/></svg></div>
      <div class="mq3-tile" style="--hue:60"><svg viewBox="0 0 160 120"><rect x="14" y="16" width="92" height="24" rx="12" fill="#fff" opacity=".9"/><rect x="54" y="48" width="92" height="24" rx="12" fill="#fff" opacity=".45"/><rect x="14" y="80" width="70" height="24" rx="12" fill="#fff" opacity=".9"/></svg></div>
      <div class="mq3-tile" style="--hue:300"><svg viewBox="0 0 160 120"><rect x="14" y="14" width="44" height="7" rx="3.5" fill="#fff" opacity=".9"/><text x="14" y="50" font-size="22" font-weight="700" fill="#fff">+38%</text><path d="M14 100c16-4 22-24 38-22s22 14 36 4 20-30 36-32 16 6 22 4" fill="none" stroke="#fff" stroke-width="4" stroke-linecap="round" opacity=".9"/></svg></div>
      <div class="mq3-tile" style="--hue:280"><svg viewBox="0 0 160 120"><circle cx="118" cy="34" r="14" fill="#fff" opacity=".85"/><path d="M0 120V92l34-30 26 22 30-36 70 72z" fill="#fff" opacity=".35"/><path d="M0 120v-14l40-26 40 24 36-20 44 36z" fill="#fff" opacity=".6"/></svg></div>
      <div class="mq3-tile" style="--hue:250"><svg viewBox="0 0 160 120"><circle cx="40" cy="44" r="20" fill="#fff" opacity=".9"/><rect x="70" y="32" width="70" height="8" rx="4" fill="#fff" opacity=".9"/><rect x="70" y="48" width="48" height="6" rx="3" fill="#fff" opacity=".55"/><rect x="16" y="80" width="128" height="26" rx="8" fill="#fff" opacity=".25"/><rect x="26" y="89" width="60" height="8" rx="4" fill="#fff" opacity=".8"/></svg></div>
      <div class="mq3-tile" style="--hue:20"><svg viewBox="0 0 160 120"><rect x="14" y="14" width="60" height="7" rx="3.5" fill="#fff" opacity=".9"/><rect x="14" y="26" width="38" height="5" rx="2.5" fill="#fff" opacity=".5"/><g fill="#fff" opacity=".85"><rect x="18" y="78" width="14" height="26" rx="3"/><rect x="40" y="62" width="14" height="42" rx="3"/><rect x="62" y="70" width="14" height="34" rx="3"/><rect x="84" y="50" width="14" height="54" rx="3"/><rect x="106" y="40" width="14" height="64" rx="3"/><rect x="128" y="56" width="14" height="48" rx="3"/></g></svg></div>
      <div class="mq3-tile" style="--hue:160"><svg viewBox="0 0 160 120"><rect x="14" y="14" width="56" height="8" rx="4" fill="#fff" opacity=".9"/><rect x="14" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="71" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="34" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="33" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="128" y="53" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="52" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="90" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="72" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="14" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="33" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/><rect x="52" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="71" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="90" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="109" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.35"/><rect x="128" y="91" width="14" height="14" rx="4" fill="#fff" opacity="0.9"/></svg></div>
    </mv-marquee>
  </div>
</div>

API

Attributes

NameTypeDefaultDescription
speednumber40Speed in pixels per second (independent of the content width).
verticalbooleanVertical scrolling (height via --mv-marquee-height).
reversebooleanReverses the scroll direction.
pause-on-hoverbooleanSmoothly slows to a stop on mouse hover.
fadebooleanMasked edge fade (radial in the 3D variant).
dragbooleanGrab with mouse or finger, with inertia on release; arrow keys when the marquee has focus.
data-variant3dPerspective-tilted plane: children are spread across vertical columns scrolling in alternating directions.
columnsnumber4Number of columns in the 3D variant.

Methods

NameDescription
refresh()Rebuilds the copies after the children change.

Content structure

NameDescription
childrenItems to scroll (logos, cards…). They stay accessible; the filler copies are aria-hidden and inert.

CSS classes

NameDescription
mv-marquee-lane / -track / -group / -copyGenerated structure (track, original group, copies).

CSS variables

NameDefaultDescription
--mv-marquee-gapvar(--mv-space-4)Space between items (and between loops).
--mv-marquee-fade12%Length of the edge fade.
--mv-marquee-height20rem (3D: 28rem)Height in vertical and 3D modes.
--mv-marquee-padding0Vertical inner padding (gives shadows room to breathe).
--mv-marquee-tilt-x / --mv-marquee-tilt-z52deg / -42degTilt of the 3D plane.
--mv-marquee-perspective2400pxPerspective of the 3D variant.

Accessibility

The original content stays in the accessibility tree; the copies are aria-hidden + inert (no duplicates for keyboard or screen reader users). Scrolling stops when focus enters the marquee (WCAG 2.2.2) and on hover with pause-on-hover. Under reduced motion: a static, natively scrollable row without copies. The loop is suspended off-screen and in hidden tabs.