Marquee

v1.0.05,3 kB gzipfree

A marquee that runs forever — built from your own elements, in any direction, at the same speed on every screen width.

Tutorial video
You can build this with AI, the prompt is ready
View live demoGet the cloneable
The principle · Why Marquee

An interaction runs over a fixed duration. The same path is longer on a 1440 screen than on a 390 one — up there the band races, down here it crawls. Here the width of your content is measured and the duration derived from it. The speed stays what you wrote down.

sfixed duration per screen
px/ssame speed everywhere
  1. WrapperThe visible cutout. Anything reaching beyond it is hidden.
  2. TrackIts children form one repetition. They are grouped and copied until the cutout is filled twice over.
  3. LoopThe track travels exactly one repetition. At the end the next copy sits where the first began — the seam is invisible.

Add this <script> to your project's custom code

Once per project is enough, even if you use the solution on several pages: Project Settings → Custom Code → Head Code. The script loads alongside the page without holding up rendering; it runs once the page is in place and does nothing while no fpu attribute is there.

<!-- FlowPowerUser · Marquee -->
<script defer src="https://cdn.jsdelivr.net/npm/@flowpoweruser/attributes@1/marquee.js"></script>

Mark the cutout and the content

You need two elements, one inside the other. On the outside the wrapper — it limits what is visible and gets overflow: hidden automatically. Inside it the track, holding your elements side by side; a flex layout with a gap is the usual choice. Everything else happens on load: your elements move into a group, and that group is copied until the cutout is filled.

On the wrapperthe visible cutout
AttributeValueDescription
Turns the solution on for this marquee and limits the visible area. Required.
On the trackinside the wrapper
AttributeValueDescription
The element whose children form one repetition. Exactly those children are grouped and copied. Required.
In the Navigator
Marquee Wrapper       fpu-marquee-element="wrapper"
└─ Marquee Track      fpu-marquee-element="track"
   ├─ Logo 1
   ├─ Logo 2
   ├─ Logo 3
   └─ Logo 4

Publish and check

Publish the page and drag the browser window wider and narrower. Two things have to hold: the speed must not change, and nothing may jump or flash where the repetition starts over. If the band stands still, either the track has no content or the wrapper has no limited width — the console names both.

OptionalOnly needed when you need it. Expand
OptionalDirection, speed and pausing on hoverDefault: leftwards, 60 px/s

Without any setting the band runs leftwards at 60 pixels per second and never stops. All three values belong on the wrapper. For “up” and “down” the wrapper needs a limited height — otherwise it grows with its content and there is nothing left to hide.

On the wrapper

AttributeValueDefaultDescription
leftWhich way the band travels. For “up” and “down” the height is measured instead of the width. An unknown value falls back to “left” and writes a warning to the console.
60Speed in pixels per second. Because the duration is derived from the measured length, this speed stays the same at every screen width. Values that are not numbers, or below one, fall back to 60.
falseStops the band while the mouse is over it or something inside it holds keyboard focus. Only exactly “true” turns it on.
OptionalA button to stop itfor accessibility

Movement that runs longer than five seconds and starts on its own needs a way to stop it, per WCAG 2.2.2. That is what this element is for. It manages aria-pressed itself and toggles on every click. One caveat: the button belongs in the wrapper or next to it — never inside the track, or it gets copied along.

On the button

AttributeValueDescription
Turns the element into a toggle. Placed inside the wrapper it finds its marquee on its own. If there is only one marquee on the page, it may also sit outside.
Only needed when the button sits outside the wrapper and there is more than one marquee: wrapper and button carry the same number and thereby belong together.
OptionalSoft edges, spacing and draggingall optional

These four change nothing about the principle, only how the band feels. All of them belong on the wrapper.

On the wrapper

AttributeValueDefaultDescription
offFades the edges out so the elements do not look sharply cut off. “true” uses 48 pixels, a number sets the width yourself.
0Extra spacing in pixels between two repetitions — added on top of any gap the track already has from the Designer.
falseMakes the band grabbable with mouse or finger. A throw coasts out and blends back into the configured speed. Clicks on links inside stay clicks as long as the finger moves less than five pixels.
falseWrites one line to the browser console on start: measured length, calculated duration and how many copies were made.
More capabilities

Additional features

Anyone asking for less motion gets none
With “reduce motion” set in the operating system the band stands still — purely via CSS, no detour. The content then wraps normally instead of being cut off, so it stays fully readable.
Change the width and it measures again
Wrapper and track are observed. Drag the window, let images load in, or have a breakpoint change the layout, and the necessary copies are added and the duration recalculated.
Your interactions stay intact
The original elements are moved, not cloned — Webflow interactions on them keep working. Only the copies are clones, and those are hidden from screen readers and taken out of the tab order.
Your own code can hook in
The solution registers with the shared roof as soon as it runs. You can register beforehand as well — the callback arrives either way.