# Marquee URL: https://ark-ui.com/docs/components/marquee Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/marquee.mdx A continuous scrolling component for displaying content in a seamless loop. --- ## Features - Smooth GPU-accelerated animations with seamless looping - Horizontal and vertical scrolling with RTL support - Auto-fill mode to duplicate content - Customizable speed and spacing - Pause on hover/focus with keyboard support - Programmatic control and finite loops ## Anatomy To set up the marquee correctly, you'll need to understand its anatomy and how we name its parts. > Each part includes a `data-part` attribute to help identify them in the DOM. {/* */} ## Examples Learn how to use the `Marquee` component in your project. Let's take a look at the most basic example: **Example: basic** #### React ```tsx import { Marquee } from '@ark-ui/react/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const Basic = () => ( {items.map((item, i) => ( {item} ))} ) ``` #### Solid ```tsx import { For } from 'solid-js' import { Marquee } from '@ark-ui/solid/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const Basic = () => ( {(item) => {item}} ) ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item} {item} {/each} ``` ### Auto Fill Use the `autoFill` prop to automatically duplicate content to fill the viewport. The `spacing` prop controls the gap between duplicated content instances: **Example: auto-fill** #### React ```tsx import { Marquee } from '@ark-ui/react/marquee' const items = ['Apple', 'Banana', 'Cherry'] export const AutoFill = () => ( {items.map((item, i) => ( {item} ))} ) ``` #### Solid ```tsx import { Marquee } from '@ark-ui/solid/marquee' import { For } from 'solid-js' const items = ['Apple', 'Banana', 'Cherry'] export const AutoFill = () => ( {(item) => {item}} ) ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item} {item} {/each} ``` ### Reverse Direction Set the `reverse` prop to reverse the scroll direction: **Example: reverse** #### React ```tsx import { Marquee } from '@ark-ui/react/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const Reverse = () => ( {items.map((item, i) => ( {item} ))} ) ``` #### Solid ```tsx import { For } from 'solid-js' import { Marquee } from '@ark-ui/solid/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const Reverse = () => ( {(item) => {item}} ) ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item} {item} {/each} ``` ### Vertical Orientation Set `side="bottom"` (or `side="top"`) to create a vertical marquee: **Example: vertical** #### React ```tsx import { Marquee } from '@ark-ui/react/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const Vertical = () => ( {items.map((item, i) => ( {item} ))} ) ``` #### Solid ```tsx import { For } from 'solid-js' import { Marquee } from '@ark-ui/solid/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const Vertical = () => ( {(item) => {item}} ) ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item} {item} {/each} ``` ### Custom Speed Control the animation speed using the `speed` prop, which accepts values in pixels per second: **Example: speed** #### React ```tsx import { Marquee } from '@ark-ui/react/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const Speed = () => (

Slow (25px/s)

{items.map((item, i) => ( {item} ))}

Normal (50px/s)

{items.map((item, i) => ( {item} ))}

Fast (100px/s)

{items.map((item, i) => ( {item} ))}
) ``` #### Solid ```tsx import { For } from 'solid-js' import { Marquee } from '@ark-ui/solid/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const Speed = () => (

Slow (25px/s)

{(item) => {item}}

Normal (50px/s)

{(item) => {item}}

Fast (100px/s)

{(item) => {item}}
) ``` #### Vue ```vue ``` #### Svelte ```svelte

Slow (25px/s)

{#each items as item} {item} {/each}

Normal (50px/s)

{#each items as item} {item} {/each}

Fast (100px/s)

{#each items as item} {item} {/each}
``` ### Pause on Interaction Enable `pauseOnInteraction` to pause the marquee when users hover or focus on it, improving accessibility: **Example: pause-on-interaction** #### React ```tsx import { Marquee } from '@ark-ui/react/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const PauseOnInteraction = () => ( {items.map((item, i) => ( {item} ))} ) ``` #### Solid ```tsx import { For } from 'solid-js' import { Marquee } from '@ark-ui/solid/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const PauseOnInteraction = () => ( {(item) => {item}} ) ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item} {item} {/each} ``` ### Programmatic Control Use the `useMarquee` hook with `Marquee.RootProvider` to access the marquee API and control playback programmatically: **Example: programmatic-control** #### React ```tsx import { Marquee, useMarquee } from '@ark-ui/react/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const ProgrammaticControl = () => { const marquee = useMarquee() return ( <> {items.map((item, i) => ( {item} ))}
) } ``` #### Solid ```tsx import { For } from 'solid-js' import { Marquee, useMarquee } from '@ark-ui/solid/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const ProgrammaticControl = () => { const marquee = useMarquee() return ( <> {(item) => {item}}
) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item} {item} {/each}
``` > If you're using the `Marquee.RootProvider` component, you don't need to use the `Marquee.Root` component. ### Finite Loops Set the `loopCount` prop to run the marquee a specific number of times. Use `onLoopComplete` to track each loop iteration and `onComplete` to know when all loops finish: **Example: finite-loops** #### React ```tsx import { useState } from 'react' import { Marquee } from '@ark-ui/react/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const FiniteLoops = () => { const [loopCount, setLoopCount] = useState(0) const [completedCount, setCompletedCount] = useState(0) return ( <> setLoopCount((prev) => prev + 1)} onComplete={() => setCompletedCount((prev) => prev + 1)} > {items.map((item, i) => ( {item} ))}

Loop completed: {loopCount} times

Animation completed: {completedCount} times

) } ``` #### Solid ```tsx import { For, createSignal } from 'solid-js' import { Marquee } from '@ark-ui/solid/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const FiniteLoops = () => { const [loopCount, setLoopCount] = createSignal(0) const [completedCount, setCompletedCount] = createSignal(0) return ( <> setLoopCount((prev) => prev + 1)} onComplete={() => setCompletedCount((prev) => prev + 1)} > {(item) => {item}}

Loop completed: {loopCount()} times

Animation completed: {completedCount()} times

) } ``` #### Vue ```vue ``` #### Svelte ```svelte loopCount++} onComplete={() => completedCount++} > {#each items as item} {item} {/each}

Loop completed: {loopCount} times

Animation completed: {completedCount} times

``` ### Edge Gradients Add `Marquee.Edge` components to create fade effects at the start and end of the scrolling area: **Example: with-edges** #### React ```tsx import { Marquee } from '@ark-ui/react/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const WithEdges = () => ( {items.map((item, i) => ( {item} ))} ) ``` #### Solid ```tsx import { For } from 'solid-js' import { Marquee } from '@ark-ui/solid/marquee' const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'] export const WithEdges = () => ( {(item) => {item}} ) ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item} {item} {/each} ``` ## Guides ### Styling Requirements The Marquee component requires CSS keyframe animations to function properly. You'll need to define animations for both horizontal and vertical scrolling: ```css @keyframes marqueeX { from { transform: translateX(0); } to { transform: translateX(var(--marquee-translate)); } } @keyframes marqueeY { from { transform: translateY(0); } to { transform: translateY(var(--marquee-translate)); } } ``` The component automatically applies the appropriate animation (`marqueeX` or `marqueeY`) based on the scroll direction and uses the `--marquee-translate` CSS variable for seamless looping. You can target specific parts of the marquee using `data-part` attributes for custom styling: - `[data-part="root"]` - The root container - `[data-part="viewport"]` - The scrolling viewport - `[data-part="content"]` - The content wrapper (receives animation) - `[data-part="item"]` - Individual marquee items - `[data-part="edge"]` - Edge gradient overlays ### Best Practices - **Enable pause-on-interaction**: Use `pauseOnInteraction` to allow users to pause animations on hover or focus, improving accessibility and readability - **Use descriptive labels**: Provide meaningful `aria-label` values that describe the marquee content (e.g., "Partner logos", "Latest announcements") - **Avoid for critical information**: Don't use marquees for essential content that users must read, as continuously moving text can be difficult to process. Consider static displays for important information ## API Reference ### Props ### Context These are the properties available when using `Marquee.Context`, `useMarqueeContext` hook or `useMarquee` hook. **API:** | Property | Type | Description | |----------|------|-------------| | `paused` | `boolean` | Whether the marquee is currently paused. | | `orientation` | `"horizontal" | "vertical"` | The current orientation of the marquee. | | `side` | `Side` | The current side/direction of the marquee. | | `multiplier` | `number` | The multiplier for auto-fill. Indicates how many times to duplicate content. When autoFill is enabled and content is smaller than container, this returns the number of additional copies needed. Otherwise returns 1. | | `contentCount` | `number` | The total number of content elements to render (original + clones). Use this value when rendering your content in a loop. | | `pause` | `VoidFunction` | Pause the marquee animation. | | `resume` | `VoidFunction` | Resume the marquee animation. | | `togglePause` | `VoidFunction` | Toggle the pause state. | | `restart` | `VoidFunction` | Restart the marquee animation from the beginning. | ## Accessibility The Marquee component is built with accessibility in mind: - Uses appropriate ARIA attributes: `role="region"` and `aria-roledescription="marquee"` - Cloned content for seamless looping is marked with `aria-hidden="true"` to avoid confusion for screen readers - Automatically respects user motion preferences via `prefers-reduced-motion` - Supports keyboard interaction when `pauseOnInteraction` is enabled - Allows users to pause animations on hover or focus for better readability