Ticker
This feature is available with Motion+
The Ticker component for React creates performant, flexible, and fully accessible ticker and marquee animations. It's perfect for showcasing logos, photos, testimonials, news headlines, and more.
Ticker's simple API makes these infinitely-scrolling animations easy to build.
<Ticker items={items} />
It intelligently clones only the minimum number of items needed to create a seamless loop, ensuring optimal performance. Because it's powered by Motion, you can take full manual control with a motion value to create scroll-driven or draggable effects.
Ticker is exclusive to Motion+ members. Motion+ is a one-time payment, lifetime membership that unlocks exclusive components, premium examples and access to a private Discord community.
Features
Ticker is a production-ready component built with performance and accessibility at its core.
Lightweight: Just
+2.1kbon top of Motion for React.Accessible: Automatic support for "reduced motion" and intelligent keyboard focus-trapping means your site is inclusive for all users.
Flexible: Animate horizontally or vertically. Control the animation with velocity, scroll position, or drag gestures.
Performant: Creates the absolute minimum number of cloned elements required to fill the viewport. Read more about Motion+ Ticker's unique renderer. More efficient and maintainable than hand-rolled CSS tickers.
Full-width overflow: Easily create tickers that are contained within your layout but visually extend to the edges of the viewport.
RTL-compatible: Automatically adapts to RTL layouts.
Install
First, add the Motion+ library to your project using your private token. You need to be a Motion+ member to generate a private token.
npm install https://api.motion.dev/registry\?package\=motion-plus\&version\=2.0.0-alpha.4\&token
Once installed, Ticker can be imported via motion-plus/react:
import { Ticker } from "motion-plus/react"
Usage
Ticker accepts on mandatory prop, items. This is a list of valid React nodes (which can be components, strings or numbers):
const items = [ <span>One</span>, <span>Two</span>, <span>Three</span> ] return <Ticker items={items} />
Direction
By default, tickers will scroll horizontally, but via the axis prop we can lay out and animate items on the "y" axis too.
<Ticker items={items} axis="y" />
Adjust speed
Setting the velocity prop (in pixels per second) will change the speed and direction of the ticker animation.
<Ticker items={items} velocity={100} />
Flipping this to a negative value will reverse the direction of the ticker.
<Ticker items={items} velocity={-100} />
Whereas setting it to 0 will stop all motion.
<Ticker items={items} velocity={0} />
Adjust speed on hover
To adjust the speed of a ticker when it receives hover, hoverFactor can be set as a multiplicative number.
For example, setting it to 0 will stop the ticker on hover.
<Ticker items={items} hoverFactor={0} />
Whereas setting it to 0.5 would slow the ticker animation by half during the hover.
<Ticker items={items} hoverFactor={0.5} />
Layout
Items are laid out across the selected axis using flexbox. By passing gap and align props, we can adjust the spacing and off-axis alignment of the items.
<Ticker items={items} gap={0} align="start" />
Overflow
By setting overflow to true, items will visually extend out from the container to the edges of the viewport.
<Ticker items={items} overflow />
This makes it straightforward to place a Ticker within a document flow but still extend the ticker effect across the full viewport.
Manual control
By default, the ticker controls its own offset via an internally-created motion value.
By passing a different motion value via the offset prop, we can take manual control of the offset.
const offset = useMotionValue(0) return <Ticker items={items} offset={offset} />
Now, when the offset motion value is changed, the offset of the ticker will update.
<button onClick={() => offset.set(-100)} />
Any motion value can be passed into the ticker, like those returned from useScroll or ones wired up to the drag gesture.
Animate items with ticker scroll
The useTickerItem hook returns information about the item that you can use to create bespoke per-item animations.
It returns:
offset: AMotionValuethat represents the item's scroll offset relative to the container. At0, the item is visually aligned to the start of the ticker. Note that this will be flipped in RTL layouts.start/end: The start and end boundaries of the item layout within the ticker. Note that these are reversed in RTL layouts.itemIndex: Theindexof this item. For clones, thisindexvalue will represent the index value of the original item.
function Item() { const { offset } = useTickerItem() const rotate = useTransform(offset, [0, 300], [0, 360], { clamp: false }) return ( <motion.div style={{ rotate }}> 😂 </motion.div> ) }
<Ticker items={[<Item />]} />
Accessibility
Reduced motion
Unless offset is defined, Ticker automatically respects the OS "reduced motion" setting.
Keyboard navigation
Ticker will detect if any item within it receives focus via keypress. The animation will stop, and the first item inside the ticker will receive focus.
From here, left/right arrows (or up/down for axis="y") can be used to navigate between focusable elements within the original (not cloned) items. Tab or shift-tab will break this focus trap.
This approach ensures tickers with many items don't hog keyboard navigation.
Options
Ticker renders a motion.div, so it supports most of the same props. It also supports the following options:
items
Required. An array of strings or React components to render. This list will be cloned as many times as needed to visually fill the ticker.
const items = [ <span>One</span>, <span>Two</span>, <span>Three</span> ] return <Ticker items={items} />
axis
Default: "x"
Determines on which axis the ticker should lay out and repeat items.
velocity
Default: 50
The velocity of the ticker scroll animation in pixels per second.
<Ticker items={items} velocity={-50} /> // Reversed
<Ticker items={items} velocity={0} /> // Stopped
Note: The velocity provided to Ticker will automatically be flipped in RTL layouts.
hoverFactor
Default: 1
A factor to apply to the current velocity when the ticker is hovered.
<Ticker items={items} hoverFactor={0} /> // Will stop on hover
<Ticker items={items} hoverFactor={0.5} /> // Will half speed on hover
gap
Default: 10
A gap to apply between items, in pixels.
align
Default: "center"
Alignment of items within the ticker's off-axis. For example, if this is a y-axis ticker, this will align items horizontally within the ticker.
Can be set to "start", "center" or "end".
offset
A motion value to externally control ticker offset.
If provided, this option will disable the automatic ticker animation.
const { scrollY } = useScroll() const invertScroll = useTransform(() => scrollY.get() * -1) return <Ticker items={items} offset={invertScroll} />
The Ticker renders its items in such a way that offset can be set to any numerical value, and it will be correctly wrapped so that items display correctly on screen.
fade
Default: 0
Fades the content out at each end of the carousel container. Can be set either as a number (pixels) or %.
<Ticker items={items} fade={100} />
safeMargin
Default: 0
Ticker uses a unique reprojection renderer, which can reduce or eliminate item cloning. Technically, this works by reprojecting items that disappear off the start of the visible area over to the end.
The calculation for this is based on the item and ticker container's layout. If you're rotating the ticker, or transforming its items in some way that brings them back inside the visible area, you may see items disappear as they reproject. If so, you can use safeMargin to increase the visible area to compensate.
<Ticker items={items} safeMargin={100} />
as
Default: "div"
The HTML element to use to render the ticker container.
<Ticker items={items} as="section" />
The Ticker component for React creates performant, flexible, and fully accessible ticker and marquee animations. It's perfect for showcasing logos, photos, testimonials, news headlines, and more.
Ticker's simple API makes these infinitely-scrolling animations easy to build.
<Ticker items={items} />
It intelligently clones only the minimum number of items needed to create a seamless loop, ensuring optimal performance. Because it's powered by Motion, you can take full manual control with a motion value to create scroll-driven or draggable effects.
Ticker is exclusive to Motion+ members. Motion+ is a one-time payment, lifetime membership that unlocks exclusive components, premium examples and access to a private Discord community.
Features
Ticker is a production-ready component built with performance and accessibility at its core.
Lightweight: Just
+2.1kbon top of Motion for React.Accessible: Automatic support for "reduced motion" and intelligent keyboard focus-trapping means your site is inclusive for all users.
Flexible: Animate horizontally or vertically. Control the animation with velocity, scroll position, or drag gestures.
Performant: Creates the absolute minimum number of cloned elements required to fill the viewport. Read more about Motion+ Ticker's unique renderer. More efficient and maintainable than hand-rolled CSS tickers.
Full-width overflow: Easily create tickers that are contained within your layout but visually extend to the edges of the viewport.
RTL-compatible: Automatically adapts to RTL layouts.
Install
First, add the Motion+ library to your project using your private token. You need to be a Motion+ member to generate a private token.
npm install https://api.motion.dev/registry\?package\=motion-plus\&version\=2.0.0-alpha.4\&token
Once installed, Ticker can be imported via motion-plus/react:
import { Ticker } from "motion-plus/react"
Usage
Ticker accepts on mandatory prop, items. This is a list of valid React nodes (which can be components, strings or numbers):
const items = [ <span>One</span>, <span>Two</span>, <span>Three</span> ] return <Ticker items={items} />
Direction
By default, tickers will scroll horizontally, but via the axis prop we can lay out and animate items on the "y" axis too.
<Ticker items={items} axis="y" />
Adjust speed
Setting the velocity prop (in pixels per second) will change the speed and direction of the ticker animation.
<Ticker items={items} velocity={100} />
Flipping this to a negative value will reverse the direction of the ticker.
<Ticker items={items} velocity={-100} />
Whereas setting it to 0 will stop all motion.
<Ticker items={items} velocity={0} />
Adjust speed on hover
To adjust the speed of a ticker when it receives hover, hoverFactor can be set as a multiplicative number.
For example, setting it to 0 will stop the ticker on hover.
<Ticker items={items} hoverFactor={0} />
Whereas setting it to 0.5 would slow the ticker animation by half during the hover.
<Ticker items={items} hoverFactor={0.5} />
Layout
Items are laid out across the selected axis using flexbox. By passing gap and align props, we can adjust the spacing and off-axis alignment of the items.
<Ticker items={items} gap={0} align="start" />
Overflow
By setting overflow to true, items will visually extend out from the container to the edges of the viewport.
<Ticker items={items} overflow />
This makes it straightforward to place a Ticker within a document flow but still extend the ticker effect across the full viewport.
Manual control
By default, the ticker controls its own offset via an internally-created motion value.
By passing a different motion value via the offset prop, we can take manual control of the offset.
const offset = useMotionValue(0) return <Ticker items={items} offset={offset} />
Now, when the offset motion value is changed, the offset of the ticker will update.
<button onClick={() => offset.set(-100)} />
Any motion value can be passed into the ticker, like those returned from useScroll or ones wired up to the drag gesture.
Animate items with ticker scroll
The useTickerItem hook returns information about the item that you can use to create bespoke per-item animations.
It returns:
offset: AMotionValuethat represents the item's scroll offset relative to the container. At0, the item is visually aligned to the start of the ticker. Note that this will be flipped in RTL layouts.start/end: The start and end boundaries of the item layout within the ticker. Note that these are reversed in RTL layouts.itemIndex: Theindexof this item. For clones, thisindexvalue will represent the index value of the original item.
function Item() { const { offset } = useTickerItem() const rotate = useTransform(offset, [0, 300], [0, 360], { clamp: false }) return ( <motion.div style={{ rotate }}> 😂 </motion.div> ) }
<Ticker items={[<Item />]} />
Accessibility
Reduced motion
Unless offset is defined, Ticker automatically respects the OS "reduced motion" setting.
Keyboard navigation
Ticker will detect if any item within it receives focus via keypress. The animation will stop, and the first item inside the ticker will receive focus.
From here, left/right arrows (or up/down for axis="y") can be used to navigate between focusable elements within the original (not cloned) items. Tab or shift-tab will break this focus trap.
This approach ensures tickers with many items don't hog keyboard navigation.
Options
Ticker renders a motion.div, so it supports most of the same props. It also supports the following options:
items
Required. An array of strings or React components to render. This list will be cloned as many times as needed to visually fill the ticker.
const items = [ <span>One</span>, <span>Two</span>, <span>Three</span> ] return <Ticker items={items} />
axis
Default: "x"
Determines on which axis the ticker should lay out and repeat items.
velocity
Default: 50
The velocity of the ticker scroll animation in pixels per second.
<Ticker items={items} velocity={-50} /> // Reversed
<Ticker items={items} velocity={0} /> // Stopped
Note: The velocity provided to Ticker will automatically be flipped in RTL layouts.
hoverFactor
Default: 1
A factor to apply to the current velocity when the ticker is hovered.
<Ticker items={items} hoverFactor={0} /> // Will stop on hover
<Ticker items={items} hoverFactor={0.5} /> // Will half speed on hover
gap
Default: 10
A gap to apply between items, in pixels.
align
Default: "center"
Alignment of items within the ticker's off-axis. For example, if this is a y-axis ticker, this will align items horizontally within the ticker.
Can be set to "start", "center" or "end".
offset
A motion value to externally control ticker offset.
If provided, this option will disable the automatic ticker animation.
const { scrollY } = useScroll() const invertScroll = useTransform(() => scrollY.get() * -1) return <Ticker items={items} offset={invertScroll} />
The Ticker renders its items in such a way that offset can be set to any numerical value, and it will be correctly wrapped so that items display correctly on screen.
fade
Default: 0
Fades the content out at each end of the carousel container. Can be set either as a number (pixels) or %.
<Ticker items={items} fade={100} />
safeMargin
Default: 0
Ticker uses a unique reprojection renderer, which can reduce or eliminate item cloning. Technically, this works by reprojecting items that disappear off the start of the visible area over to the end.
The calculation for this is based on the item and ticker container's layout. If you're rotating the ticker, or transforming its items in some way that brings them back inside the visible area, you may see items disappear as they reproject. If so, you can use safeMargin to increase the visible area to compensate.
<Ticker items={items} safeMargin={100} />
as
Default: "div"
The HTML element to use to render the ticker container.
<Ticker items={items} as="section" />
The Ticker component for React creates performant, flexible, and fully accessible ticker and marquee animations. It's perfect for showcasing logos, photos, testimonials, news headlines, and more.
Ticker's simple API makes these infinitely-scrolling animations easy to build.
<Ticker items={items} />
It intelligently clones only the minimum number of items needed to create a seamless loop, ensuring optimal performance. Because it's powered by Motion, you can take full manual control with a motion value to create scroll-driven or draggable effects.
Ticker is exclusive to Motion+ members. Motion+ is a one-time payment, lifetime membership that unlocks exclusive components, premium examples and access to a private Discord community.
Features
Ticker is a production-ready component built with performance and accessibility at its core.
Lightweight: Just
+2.1kbon top of Motion for React.Accessible: Automatic support for "reduced motion" and intelligent keyboard focus-trapping means your site is inclusive for all users.
Flexible: Animate horizontally or vertically. Control the animation with velocity, scroll position, or drag gestures.
Performant: Creates the absolute minimum number of cloned elements required to fill the viewport. Read more about Motion+ Ticker's unique renderer. More efficient and maintainable than hand-rolled CSS tickers.
Full-width overflow: Easily create tickers that are contained within your layout but visually extend to the edges of the viewport.
RTL-compatible: Automatically adapts to RTL layouts.
Install
First, add the Motion+ library to your project using your private token. You need to be a Motion+ member to generate a private token.
npm install https://api.motion.dev/registry\?package\=motion-plus\&version\=2.0.0-alpha.4\&token
Once installed, Ticker can be imported via motion-plus/react:
import { Ticker } from "motion-plus/react"
Usage
Ticker accepts on mandatory prop, items. This is a list of valid React nodes (which can be components, strings or numbers):
const items = [ <span>One</span>, <span>Two</span>, <span>Three</span> ] return <Ticker items={items} />
Direction
By default, tickers will scroll horizontally, but via the axis prop we can lay out and animate items on the "y" axis too.
<Ticker items={items} axis="y" />
Adjust speed
Setting the velocity prop (in pixels per second) will change the speed and direction of the ticker animation.
<Ticker items={items} velocity={100} />
Flipping this to a negative value will reverse the direction of the ticker.
<Ticker items={items} velocity={-100} />
Whereas setting it to 0 will stop all motion.
<Ticker items={items} velocity={0} />
Adjust speed on hover
To adjust the speed of a ticker when it receives hover, hoverFactor can be set as a multiplicative number.
For example, setting it to 0 will stop the ticker on hover.
<Ticker items={items} hoverFactor={0} />
Whereas setting it to 0.5 would slow the ticker animation by half during the hover.
<Ticker items={items} hoverFactor={0.5} />
Layout
Items are laid out across the selected axis using flexbox. By passing gap and align props, we can adjust the spacing and off-axis alignment of the items.
<Ticker items={items} gap={0} align="start" />
Overflow
By setting overflow to true, items will visually extend out from the container to the edges of the viewport.
<Ticker items={items} overflow />
This makes it straightforward to place a Ticker within a document flow but still extend the ticker effect across the full viewport.
Manual control
By default, the ticker controls its own offset via an internally-created motion value.
By passing a different motion value via the offset prop, we can take manual control of the offset.
const offset = useMotionValue(0) return <Ticker items={items} offset={offset} />
Now, when the offset motion value is changed, the offset of the ticker will update.
<button onClick={() => offset.set(-100)} />
Any motion value can be passed into the ticker, like those returned from useScroll or ones wired up to the drag gesture.
Animate items with ticker scroll
The useTickerItem hook returns information about the item that you can use to create bespoke per-item animations.
It returns:
offset: AMotionValuethat represents the item's scroll offset relative to the container. At0, the item is visually aligned to the start of the ticker. Note that this will be flipped in RTL layouts.start/end: The start and end boundaries of the item layout within the ticker. Note that these are reversed in RTL layouts.itemIndex: Theindexof this item. For clones, thisindexvalue will represent the index value of the original item.
function Item() { const { offset } = useTickerItem() const rotate = useTransform(offset, [0, 300], [0, 360], { clamp: false }) return ( <motion.div style={{ rotate }}> 😂 </motion.div> ) }
<Ticker items={[<Item />]} />
Accessibility
Reduced motion
Unless offset is defined, Ticker automatically respects the OS "reduced motion" setting.
Keyboard navigation
Ticker will detect if any item within it receives focus via keypress. The animation will stop, and the first item inside the ticker will receive focus.
From here, left/right arrows (or up/down for axis="y") can be used to navigate between focusable elements within the original (not cloned) items. Tab or shift-tab will break this focus trap.
This approach ensures tickers with many items don't hog keyboard navigation.
Options
Ticker renders a motion.div, so it supports most of the same props. It also supports the following options:
items
Required. An array of strings or React components to render. This list will be cloned as many times as needed to visually fill the ticker.
const items = [ <span>One</span>, <span>Two</span>, <span>Three</span> ] return <Ticker items={items} />
axis
Default: "x"
Determines on which axis the ticker should lay out and repeat items.
velocity
Default: 50
The velocity of the ticker scroll animation in pixels per second.
<Ticker items={items} velocity={-50} /> // Reversed
<Ticker items={items} velocity={0} /> // Stopped
Note: The velocity provided to Ticker will automatically be flipped in RTL layouts.
hoverFactor
Default: 1
A factor to apply to the current velocity when the ticker is hovered.
<Ticker items={items} hoverFactor={0} /> // Will stop on hover
<Ticker items={items} hoverFactor={0.5} /> // Will half speed on hover
gap
Default: 10
A gap to apply between items, in pixels.
align
Default: "center"
Alignment of items within the ticker's off-axis. For example, if this is a y-axis ticker, this will align items horizontally within the ticker.
Can be set to "start", "center" or "end".
offset
A motion value to externally control ticker offset.
If provided, this option will disable the automatic ticker animation.
const { scrollY } = useScroll() const invertScroll = useTransform(() => scrollY.get() * -1) return <Ticker items={items} offset={invertScroll} />
The Ticker renders its items in such a way that offset can be set to any numerical value, and it will be correctly wrapped so that items display correctly on screen.
fade
Default: 0
Fades the content out at each end of the carousel container. Can be set either as a number (pixels) or %.
<Ticker items={items} fade={100} />
safeMargin
Default: 0
Ticker uses a unique reprojection renderer, which can reduce or eliminate item cloning. Technically, this works by reprojecting items that disappear off the start of the visible area over to the end.
The calculation for this is based on the item and ticker container's layout. If you're rotating the ticker, or transforming its items in some way that brings them back inside the visible area, you may see items disappear as they reproject. If so, you can use safeMargin to increase the visible area to compensate.
<Ticker items={items} safeMargin={100} />
as
Default: "div"
The HTML element to use to render the ticker container.
<Ticker items={items} as="section" />

