# 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. --- ## Anatomy {/* */} ```tsx ``` ## Examples **Example: basic** ```ripple import { Marquee } from 'ark-ripple/marquee'; import styles from 'styles/marquee.module.css'; const items = [ { name: 'Apple', logo: '🍎' }, { name: 'Banana', logo: '🍌' }, { name: 'Cherry', logo: '🍒' }, { name: 'Grape', logo: '🍇' }, { name: 'Watermelon', logo: '🍉' }, { name: 'Strawberry', logo: '🍓' }, ]; export component Basic() { for (const item of items; key item.name) { {item.logo} {item.name} } } ``` ### 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** ```ripple import { Marquee } from 'ark-ripple/marquee'; import styles from 'styles/marquee.module.css'; const items = [ { name: 'Apple', logo: '🍎' }, { name: 'Banana', logo: '🍌' }, { name: 'Cherry', logo: '🍒' }, ]; export component AutoFill() { for (const item of items; key item.name) { {item.logo} {item.name} } } ``` ### Reverse Set the `reverse` prop to reverse the scroll direction: **Example: reverse** ```ripple import { Marquee } from 'ark-ripple/marquee'; import styles from 'styles/marquee.module.css'; const items = [ { name: 'Apple', logo: '🍎' }, { name: 'Banana', logo: '🍌' }, { name: 'Cherry', logo: '🍒' }, { name: 'Grape', logo: '🍇' }, { name: 'Watermelon', logo: '🍉' }, { name: 'Strawberry', logo: '🍓' }, ]; export component Reverse() { for (const item of items; key item.name) { {item.logo} {item.name} } } ``` ### Vertical Set `side="bottom"` (or `side="top"`) to create a vertical marquee: **Example: vertical** ```ripple import { Marquee } from 'ark-ripple/marquee'; import styles from 'styles/marquee.module.css'; const items = [ { name: 'Apple', logo: '🍎' }, { name: 'Banana', logo: '🍌' }, { name: 'Cherry', logo: '🍒' }, { name: 'Grape', logo: '🍇' }, { name: 'Watermelon', logo: '🍉' }, { name: 'Strawberry', logo: '🍓' }, ]; export component Vertical() { for (const item of items; key item.name) { {item.logo} {item.name} } } ``` ### Speed Control the animation speed using the `speed` prop, which accepts values in pixels per second: **Example: speed** ```ripple import { Marquee } from 'ark-ripple/marquee'; import styles from 'styles/marquee.module.css'; const items = [ { name: 'Apple', logo: '🍎' }, { name: 'Banana', logo: '🍌' }, { name: 'Cherry', logo: '🍒' }, { name: 'Grape', logo: '🍇' }, { name: 'Watermelon', logo: '🍉' }, { name: 'Strawberry', logo: '🍓' }, ]; export component Speed() {

{'Slow (25px/s)'}

for (const item of items; key item.name) { {item.logo} {item.name} }

{'Normal (50px/s)'}

for (const item of items; key item.name) { {item.logo} {item.name} }

{'Fast (100px/s)'}

for (const item of items; key item.name) { {item.logo} {item.name} }
} ``` ### Pause on Interaction Enable `pauseOnInteraction` to pause the marquee when users hover or focus on it, improving accessibility: **Example: pause-on-interaction** ```ripple import { Marquee } from 'ark-ripple/marquee'; import styles from 'styles/marquee.module.css'; const items = [ { name: 'Apple', logo: '🍎' }, { name: 'Banana', logo: '🍌' }, { name: 'Cherry', logo: '🍒' }, { name: 'Grape', logo: '🍇' }, { name: 'Watermelon', logo: '🍉' }, { name: 'Strawberry', logo: '🍓' }, ]; export component PauseOnInteraction() { for (const item of items; key item.name) { {item.logo} {item.name} } } ``` ### Programmatic Control Use the `useMarquee` hook with `Marquee.RootProvider` to access the marquee API and control playback programmatically: **Example: programmatic-control** ```ripple import { Marquee, useMarquee } from 'ark-ripple/marquee'; import button from 'styles/button.module.css'; import styles from 'styles/marquee.module.css'; const items = [ { name: 'Apple', logo: '🍎' }, { name: 'Banana', logo: '🍌' }, { name: 'Cherry', logo: '🍒' }, { name: 'Grape', logo: '🍇' }, { name: 'Watermelon', logo: '🍉' }, { name: 'Strawberry', logo: '🍓' }, ]; export component ProgrammaticControl() { const marquee = useMarquee({});
for (const item of items; key item.name) { {item.logo} {item.name} }
} ``` > If you're using the `Marquee.RootProvider` component, you don't need to use the `Marquee.Root` component. ### 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** ```ripple import { Marquee } from 'ark-ripple/marquee'; import { track } from 'ripple'; import styles from 'styles/marquee.module.css'; const items = [ { name: 'Apple', logo: '🍎' }, { name: 'Banana', logo: '🍌' }, { name: 'Cherry', logo: '🍒' }, { name: 'Grape', logo: '🍇' }, { name: 'Watermelon', logo: '🍉' }, { name: 'Strawberry', logo: '🍓' }, ]; export component FiniteLoops() { let loopCount = track(0); let completedCount = track(0);
{ @loopCount = @loopCount + 1; }} onComplete={() => { @completedCount = @completedCount + 1; }} class={styles.Root} > for (const item of items; key item.name) { {item.logo} {item.name} }

{'Loop completed: '} {@loopCount} {' times'}

{'Animation completed: '} {@completedCount} {' times'}

} ``` ### Edges Add `Marquee.Edge` components to create fade effects at the start and end of the scrolling area: **Example: with-edges** ```ripple import { Marquee } from 'ark-ripple/marquee'; import styles from 'styles/marquee.module.css'; const items = [ { name: 'Apple', logo: '🍎' }, { name: 'Banana', logo: '🍌' }, { name: 'Cherry', logo: '🍒' }, { name: 'Grape', logo: '🍇' }, { name: 'Watermelon', logo: '🍉' }, { name: 'Strawberry', logo: '🍓' }, ]; export component WithEdges() { for (const item of items; key item.name) { {item.logo} {item.name} } } ``` ## Guides ### Content Animation 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 **Component API Reference** **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFill` | `boolean` | No | Whether to automatically duplicate content to fill the container. | | `defaultPaused` | `boolean` | No | Whether the marquee is paused by default. | | `delay` | `number` | No | The delay before the animation starts (in seconds). | | `ids` | `Partial<{ root: string; viewport: string; content: (index: number) => string }>` | No | The ids of the elements in the marquee. Useful for composition. | | `loopCount` | `number` | No | The number of times to loop the animation (0 = infinite). | | `onComplete` | `() => void` | No | Function called when the marquee completes all loops and stops. Only fires for finite loops (loopCount > 0). | | `onLoopComplete` | `() => void` | No | Function called when the marquee completes one loop iteration. | | `onPauseChange` | `(details: PauseStatusDetails) => void` | No | Function called when the pause status changes. | | `paused` | `boolean` | No | Whether the marquee is paused. | | `pauseOnInteraction` | `boolean` | No | Whether to pause the marquee on user interaction (hover, focus). | | `reverse` | `boolean` | No | Whether to reverse the animation direction. | | `side` | `Side` | No | The side/direction the marquee scrolls towards. | | `spacing` | `string` | No | The spacing between marquee items. | | `speed` | `number` | No | The speed of the marquee animation in pixels per second. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | marquee | | `[data-part]` | root | | `[data-state]` | "paused" | "idle" | | `[data-orientation]` | The orientation of the marquee | | `[data-paused]` | Present when paused | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--marquee-duration` | The marquee duration value for the Root | | `--marquee-spacing` | The marquee spacing value for the Root | | `--marquee-delay` | The marquee delay value for the Root | | `--marquee-loop-count` | The marquee loop count value for the Root | | `--marquee-translate` | The marquee translate value for the Root | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | marquee | | `[data-part]` | | | `[data-index]` | The index of the item | | `[data-orientation]` | The orientation of the content | | `[data-side]` | | | `[data-reverse]` | | | `[data-clone]` | | **Edge Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `side` | `Side` | Yes | The side where the edge gradient should appear. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Edge Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | marquee | | `[data-part]` | | | `[data-side]` | | | `[data-orientation]` | The orientation of the edge | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseMarqueeReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Viewport Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Viewport Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | marquee | | `[data-part]` | | | `[data-orientation]` | The orientation of the viewport | | `[data-side]` | | ### Context **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. |