You Might Also Like
Marquee Footer — Free HTML CSS Auto-Scrolling Text Footer Snippet
Marquee Footer · Footers · Plain HTML & CSS · Live preview
What's included
Features
About this UI Snippet
Marquee Footer — A Continuously Scrolling Band, Built With Zero JavaScript

The oversized, endlessly scrolling word band has become a recognisable closing gesture on agency and product sites — it's motion with no functional job beyond signalling "this brand has energy," which makes it a good fit specifically for a footer, where there's no content hierarchy left to protect. This snippet builds the effect the same way the site's standalone Marquee does, scaled up to footer-headline size and paired with a slim, conventional link row underneath.
Duplicate the content once, animate to exactly -50%
The core trick is deceptively simple: .mqf-track contains the same sequence of words twice in a row, laid out with display: flex; width: max-content so the track is exactly twice as wide as one copy of the content. A @keyframes animation moves it from translateX(0) to translateX(-50%) — precisely one copy's width — over 22 seconds, linear. Because the second copy is identical to the first, the instant the animation resets from -50% back to 0%, the visual is indistinguishable from where it started; there's no visible seam or jump, just an apparently infinite loop built from a track that's secretly only two repeats long.
Why `width: max-content` isn't optional
Without width: max-content, the flex track would shrink or grow to fit its parent's width rather than its content's natural width, which breaks the "-50% equals exactly one copy" math the whole animation depends on. max-content forces the track to be exactly as wide as its content demands, so the halfway point of the animation always lands exactly where the first copy ends and the second begins.
Masking the hard edges
-webkit-mask / mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent) fades the marquee's opacity to zero at both edges of its container. Without this, words would appear to be cut off mid-character at the left and right boundaries as they scroll past — the mask gives the illusion that text is fading into the page edges rather than being clipped by a hard rectangle.
Pausing on hover, and turning it off entirely
.mqf:hover .mqf-track { animation-play-state: paused } freezes the scroll the moment a cursor enters the footer, which matters for a footer specifically because it often contains real, clickable content (the link row below) that a user might be trying to read or interact with while the marquee is technically still "behind" their attention. A separate prefers-reduced-motion: reduce query removes the animation and switches the track to overflow-x: auto, so motion-sensitive users get a manually scrollable strip instead of continuous, uncontrollable movement.
Build with AI
Build, Understand, Optimize, and Extend It With AI
Paste this snippet's HTML and CSS into an AI coding assistant like Claude and ask it to explain precisely why the content must be duplicated exactly twice (not three or four times) for the translateX(-50%) animation to loop seamlessly, and what would visually happen — a visible jump or gap — if you changed the animation's end value without also changing how many times the content repeats. It's also worth asking for an accessibility pass: since the marquee text is marked aria-hidden, confirm that the same information (if any is meaningful rather than purely decorative) is available elsewhere on the page for screen reader users. For extending it, ask for a version with two rows scrolling in opposite directions for a busier effect, or one where the scroll speed subtly increases based on how far down the page the user has scrolled, tying the motion to engagement rather than a fixed timer.
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:
Build a website footer topped with a large, continuously scrolling "marquee" text band, in plain HTML and CSS only — no JavaScript, no canvas.
Requirements:
- A full-width marquee strip above the main footer content, containing a flex track with a short repeating phrase (or a couple of alternating phrases separated by a small dot character) rendered at large, bold display type (roughly 28-48px, responsive via clamp()) in a single row.
- Duplicate the entire sequence of phrases exactly twice inside the track so the track's total content is precisely double one full repeat, then animate the track from translateX(0) to translateX(-50%) linearly over roughly 20-25 seconds, looping infinitely — this exact doubling is what makes the loop seamless with no visible jump.
- Give the track width: max-content so its width is determined by its content rather than its container, which the -50% animation math depends on.
- Apply a CSS mask (linear-gradient from transparent to opaque to transparent, horizontally) to the marquee's outer container so the scrolling text fades out at both edges instead of being abruptly clipped.
- Pause the scroll animation when the user's cursor is anywhere over the footer (using animation-play-state: paused via a hover selector on the footer), and resume it on mouseleave.
- Add a prefers-reduced-motion media query that removes the animation entirely and makes the marquee container horizontally scrollable instead, for users who have that OS setting enabled.
- Below the marquee, include a slim, conventional footer row: a brand name, a handful of navigation links, and a copyright line.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.
Step by step
How to Use
- 1Paste HTML and CSSA large, continuously scrolling word band renders above a standard link row — no JavaScript is used.
- 2Hover the footerThe marquee pauses while your cursor is anywhere inside the footer, then resumes when you leave.
- 3Edit the marquee wordsReplace the repeated span content — keep the sequence duplicated exactly twice for the loop to stay seamless.
- 4Adjust the scroll speedChange the 22s duration in @keyframes mqfScroll — shorter is faster, longer is slower.
- 5Update the link row and copyrightReplace the brand, footer links, and copyright text in .mqf-inner with your own.
- 6Export in your formatClick HTML, JSX, or Tailwind to download the version you need.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
The animation moves the track exactly -50% of its total width, which by construction equals the width of one copy of the content. Because the second copy is identical to the first, the loop point is invisible — the track appears to scroll forever even though only two repeats actually exist in the DOM.
Without it, the flex track would size itself to its parent container rather than to the natural width of its content, which breaks the assumption that -50% equals exactly one copy's width. max-content forces the track to be exactly as wide as the doubled content requires.
Edit the duration in the @keyframes mqfScroll animation declaration (default 22s) — a shorter duration scrolls faster, a longer one scrolls slower. The distance travelled (-50%) does not need to change.
It scrolls continuously by default, but pauses the instant the cursor enters the footer via animation-play-state: paused on hover, and stops entirely for users with prefers-reduced-motion: reduce enabled, who get a manually scrollable strip instead.
A CSS mask (linear-gradient from transparent to opaque to transparent) is applied to the marquee's container, fading its opacity toward both edges. Without it, characters would appear abruptly clipped by the container's hard rectangular boundary as they scroll past.
Click JSX, Vue, or Angular to download the converted component. Since the animation is pure CSS with no JavaScript behaviour, the conversion is a direct markup and class-name translation — just keep the duplicated content sequence intact.