Scroll & Viewport

Marquee

An endless row or column of content that can reverse, run vertically and pause on hover.

Marquee repeats the default slot enough times to fill the loop and then slides the whole row by exactly one copy, so the seam never shows. Two copies are enough for a short row; more keep the track wider than the viewport when the items are small.

Three things separate it from InfiniteSlider: it can run the other way, it can stack vertically, and it can stop while the pointer is over it. Duration is the time for one pass, so the speed follows from the content width rather than from a fixed number of pixels per second.

Usage

Motion
Nuxt UI
Tailwind
TypeScript
Vite
VueUse
Pinia
<script setup lang="ts">
const items = ['Motion', 'Nuxt UI', 'Tailwind', 'TypeScript', 'Vite', 'VueUse', 'Pinia']
</script>

<template>
  <MMarquee
    :duration="22"
    :gap="12"
    pause-on-hover
  >
    <div
      v-for="item in items"
      :key="item"
      class="flex h-12 shrink-0 items-center gap-2 rounded-lg border border-default bg-elevated px-5 text-sm font-medium text-muted"
    >
      <span class="size-1.5 rounded-full bg-primary" />
      {{ item }}
    </div>
  </MMarquee>
</template>

Examples

Customize

Motion

Customize

Duration22
Gap12
Pause on hover
Repeat6
Reverse
Vertical

Props

Prop Type Default Description
durationnumber40Seconds for one full pass. Halve it to double the speed.
gapnumber16Space between two items, in pixels. The same gap is used between the copies, so the loop stays even.
repeatnumber4How many copies of the slot to render. Raise it when the items are narrower than the container.
reversebooleanfalseSlide the content the other way. The keyframes are played backwards, so the timing stays the same.
verticalbooleanfalseStack the items in a column and scroll from bottom to top.
pauseOnHoverbooleanfalseFreeze the track while the pointer is over it, so a link inside the row stays reachable.
classstring''CSS classes for the viewport. It clips the track, so it needs a width, or a parent that gives it one.

Slots

Slot Props Description
default-The content to repeat. It is rendered once per copy, so keep it free of ids and event handlers that must stay unique.

UI

This component's theme exposes the slots below. Override any of them per instance with the ui prop, or app-wide under ui.marquee in app.config.ts.

Prop Type Default Description
uiobject-Per-slot classes merged over the theme defaults.
Slot Props Description
root-group flex overflow-hidden
track-mb-marquee-x flex w-max shrink-0
trackVertical-mb-marquee-y flex h-max shrink-0 flex-col

Accessibility

Every copy after the first is aria-hidden, so a screen reader reads the row once instead of four times. Under reduced motion the track is paused at the first copy rather than left mid-slide, and the content is still in the document and still focusable. pauseOnHover is not a substitute for keyboard access: if the row holds links, either keep it paused by default or leave the same links somewhere static on the page.

Copyright © 2026