Swiper Infinite Logo Marquee — Free JS Snippet

Swiper Infinite Logo Marquee with Hover Pause · Carousels · Plain HTML, CSS & JS · Live preview

What's included

Features

Constant-speed looping via autoplay delay 0, long speed and linear timing
slidesPerView auto so logos of any width flow naturally
Two rows moving in opposite directions using reverseDirection
Immediate freeze on hover by pinning the wrapper with getTranslate and setTranslate
Pause and Play button with aria-pressed (WCAG 2.2.2)
prefers-reduced-motion honoured on load
Touch dragging disabled for a purely decorative strip
CSS mask edge fades instead of hard clipping

About this UI Snippet

Swiper Infinite Logo Marquee — HTML, CSS & JavaScript

Screenshot of the Swiper Infinite Logo Marquee with Hover Pause snippet rendered live

The logo strip — a row of customer or partner names sliding endlessly across the page — is a landing-page staple. The common way to build it is a CSS animation on a duplicated list, which works but gives no control: you cannot easily pause it precisely, change its direction or stop it when the tab is hidden. Swiper can produce the same effect with a configuration trick, and inherits the ability to loop seamlessly, respond to touch and start or stop from code.

The trick is to make Swiper move continuously instead of in steps. Normally autoplay waits between slides and eases each move in and out, which reads as a carousel. For a marquee, set autoplay.delay to 0 so the next transition begins the instant the previous one ends, and give speed a very long duration — here six seconds per slide-width — so movement is slow and steady. Then remove the easing: Swiper's wrapper has a transition-timing-function, and forcing it to linear in CSS is what makes the speed constant rather than accelerating and decelerating. Without that one CSS line the marquee visibly pulses. slidesPerView: 'auto' with slides sized by content lets logos of different widths flow naturally, and loop: true duplicates slides behind the scenes so the strip never runs out.

Pausing takes more care than it seems. Calling autoplay.stop() does not halt movement; it lets the current transition finish, which with a six-second speed means the row keeps gliding for several seconds after the pointer arrives. To freeze immediately, the snippet reads the wrapper's current position with getTranslate(), sets the transition to zero and reapplies that translate, pinning the wrapper exactly where it is. Leaving the row calls autoplay.start() to resume. The second row uses reverseDirection: true, so the two strips travel in opposite directions, which looks livelier and avoids the two rows appearing to lock together.

Continuous motion is one of the things accessibility guidelines specifically call out. WCAG 2.2.2 requires a way to pause, stop or hide anything that moves for more than five seconds, so the snippet adds a Pause and Play button with aria-pressed, disables touch dragging because the marquee is decorative, and checks the prefers-reduced-motion media query on load so people who have asked for less movement never see it start. Edge fades are applied with a CSS mask so logos dissolve rather than being cut off.

Step by step

How to Use

  1. 1
    Watch the rowsTwo rows of logos glide at a constant speed in opposite directions, looping forever.
  2. 2
    Hover a rowMove the pointer over a row. That row freezes at once while the other keeps moving.
  3. 3
    Leave the rowMove the pointer away and the row resumes from where it stopped.
  4. 4
    Press PauseUse the Pause button to stop both rows, then press Play to restart them.
  5. 5
    Try reduced motionTurn on "reduce motion" in your operating system and reload: the marquee starts paused.

Real-world uses

Common Use Cases

🏢
Customer and partner logo strips
Show social proof under a hero with two rows moving in opposite directions, using reverseDirection for the second row.
📰
Press and publication mentions
Scroll a list of featured-in outlets at constant speed, using autoplay delay: 0 with a long speed and linear timing.
🔌
Technology and integration lists
Show the tools a product works with, using slidesPerView: 'auto' so logos of any width flow naturally.
⏱️
Autoplay progress pairing
Compare with the Swiper autoplay progress ring for content that should show when it will change rather than flow constantly.
🎓
Continuous transition learning
See why hover pause that freezes instantly needs getTranslate and setTranslate pinning the wrapper, plus a pause button and reduced-motion support.

Got questions?

Frequently Asked Questions

Set autoplay.delay to 0, give speed a large value, and set transition-timing-function: linear on the wrapper so the speed is constant.

It only prevents the next transition. The current one finishes first. To freeze at once, read getTranslate() and reapply it with setTransition(0) and setTranslate().

Use autoplay.reverseDirection: true on one of them.

For a decorative strip, no. Set allowTouchMove: false so touch does not fight the autoplay.

Provide a visible pause control, honour prefers-reduced-motion, and hide decorative content from assistive technology if it duplicates other text.

Loop mode duplicates slides, so make sure there are enough slides to fill the container width plus one full set.

Yes. Use the JSX, Vue, Angular or Tailwind export buttons on this page to convert the markup and styles. The behaviour comes from Swiper, so in a framework project install it with npm install swiper (its React and Vue components take the same options) instead of the CDN tag, use the Swiper and SwiperSlide components, or create it in useEffect / onMounted / ngAfterViewInit, and release it with destroy() when the component unmounts.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Ask an AI assistant like Claude to speed up the marquee on scroll, use real SVG logos with grayscale and colour-on-hover, or add a slower speed variant for mobile.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a two-row infinite logo marquee with Swiper 11 loaded from a CDN (bundle script and CSS).

Requirements:
- Create two Swiper instances with loop, slidesPerView 'auto', spaceBetween 14, speed 6000, freeMode, allowTouchMove: false and autoplay { delay: 0, disableOnInteraction: false }; reverseDirection on the second row.
- Force transition-timing-function: linear on .swiper-wrapper.
- On mouseenter, call autoplay.stop() and freeze immediately with getTranslate(), setTransition(0) and setTranslate(); on mouseleave call autoplay.start().
- Add a Pause/Play button with aria-pressed, and start paused when prefers-reduced-motion: reduce matches.
- Fade the edges with a CSS mask and draw the logos as coloured pill labels.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

<div class="lm-wrap">
  <p class="lm-title">Trusted by product teams at</p>
  <div class="lm-rows">
    <div class="swiper lm-swiper" id="lmA" aria-label="Customer logos, first row"><div class="swiper-wrapper"></div></div>
    <div class="swiper lm-swiper" id="lmB" aria-label="Customer logos, second row"><div class="swiper-wrapper"></div></div>
  </div>
  <div class="lm-ctl">
    <button type="button" id="lmToggle" aria-pressed="false">Pause</button>
    <span>Hover a row to pause it &middot; rows move in opposite directions</span>
  </div>
</div>