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.
| Category | Layout |
|---|---|
| Type | Web Component (<mv-marquee>) |
| Status | stable |
| Keywords | marquee, logos, testimonials, infinite-scroll, ticker, 3d, draggable |
When to use
- Customer logos, testimonials or cards should scroll in an endless loop at a constant speed
- A ticker band adds motion to a landing page and can be grabbed and dragged with inertia
- A tilted 3D wall of cards scrolling in alternating columns is wanted as a showcase
Avoid when
- A complete social-proof logo section with headline and captions is needed → use Logo Cloud instead
- Users need to deliberately browse items one at a time → use Carousel instead
- The moving content is essential reading such as prices or alerts; continuous motion makes it hard to read
Install
node scripts/add.mjs marquee --out ./src/marvelousAI 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
| Name | Type | Default | Description |
|---|---|---|---|
speed | number | 40 | Speed in pixels per second (independent of the content width). |
vertical | boolean | Vertical scrolling (height via --mv-marquee-height). | |
reverse | boolean | Reverses the scroll direction. | |
pause-on-hover | boolean | Smoothly slows to a stop on mouse hover. | |
fade | boolean | Masked edge fade (radial in the 3D variant). | |
drag | boolean | Grab with mouse or finger, with inertia on release; arrow keys when the marquee has focus. | |
data-variant | 3d | Perspective-tilted plane: children are spread across vertical columns scrolling in alternating directions. | |
columns | number | 4 | Number of columns in the 3D variant. |
Methods
| Name | Description |
|---|---|
refresh() | Rebuilds the copies after the children change. |
Content structure
| Name | Description |
|---|---|
children | Items to scroll (logos, cards…). They stay accessible; the filler copies are aria-hidden and inert. |
CSS classes
| Name | Description |
|---|---|
mv-marquee-lane / -track / -group / -copy | Generated structure (track, original group, copies). |
CSS variables
| Name | Default | Description |
|---|---|---|
--mv-marquee-gap | var(--mv-space-4) | Space between items (and between loops). |
--mv-marquee-fade | 12% | Length of the edge fade. |
--mv-marquee-height | 20rem (3D: 28rem) | Height in vertical and 3D modes. |
--mv-marquee-padding | 0 | Vertical inner padding (gives shadows room to breathe). |
--mv-marquee-tilt-x / --mv-marquee-tilt-z | 52deg / -42deg | Tilt of the 3D plane. |
--mv-marquee-perspective | 2400px | Perspective 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.