Rows of large text that drift sideways, speeding up and reversing with how fast the page is scrolled. Rows alternate direction.
Optional, and kept apart.
Nothing here is included in a project unless you add it, and the plain component it builds on is unchanged. This effect is decoration: it is hidden from screen readers, stands still for visitors who prefer reduced motion, and can be paused. Use Still on a preview to see that version.
Scroll faster
The words follow you
import { ScrollVelocity } from "@rdloom/react";
export default function ScrollVelocityBasicExample() {
return (
<div className="w-full overflow-hidden py-6">
<ScrollVelocity rows={["Scroll faster", "The words follow you"]} className="text-5xl font-bold" />
</div>
);
}Installation
npx rdloom add scroll-velocityCopies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes. It needs react-aria-components; add --install to install them.
It also adds rdloom-motion.css next to your tokens and imports it from the tokens file, once: no setup, and no inline styles. The plain components you already use are untouched.
Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/scroll-velocity.jsonWorks, but without upgrade tracking, and you import the motion CSS yourself.
Usage
import { ScrollVelocity } from "@rdloom/react";
<div className="w-full overflow-hidden py-6">
<ScrollVelocity rows={["Scroll faster", "The words follow you"]} className="text-5xl font-bold" />
</div>Single row
Design systems that move
import { ScrollVelocity } from "@rdloom/react";
export default function ScrollVelocitySingleRowExample() {
return (
<div className="w-full overflow-hidden py-6">
<ScrollVelocity rows={["Design systems that move"]} showPauseButton={false} className="text-6xl font-black" />
</div>
);
}Slow
Gentle drift
Barely moving
import { ScrollVelocity } from "@rdloom/react";
export default function ScrollVelocitySlowExample() {
return (
<div className="w-full overflow-hidden py-6">
<ScrollVelocity rows={["Gentle drift", "Barely moving"]} speed={25} velocityFactor={0.15} className="text-4xl font-semibold" />
</div>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
rowsrequiredThe text of each row. | readonly string[] | none |
speedResting speed in pixels per second. | number | 60 |
velocityFactorHow strongly page scrolling adds to the speed. 0 ignores scrolling. | number | 0.4 |
showPauseButtonShows a visible Pause and Play button (WCAG 2.2.2). | boolean | true |
pauseLabelText of the button while moving. | string | "Pause" |
playLabelText of the button while paused. | string | "Play" |
isPausedStops the animation and shows the text plainly. Moving content that lasts more than five seconds should be stoppable. | boolean | false |
Accessibility
Role text, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.
Keyboard
Not interactive.
Screen readers announce
- Each row is read once as ordinary text
What your code must do
- The text is ordinary text in the page from the server render, readable with no JavaScript, and read once by screen readers
- Decoration only: the animated layers are hidden from assistive technology and never take focus
- Stands still for visitors who ask for less motion (prefers-reduced-motion), and can also be shown still with the rdm-still class or isPaused
- In forced-colors (high contrast) mode the text is drawn in the system colours with no effect
- Does not flash: nothing changes more than three times in a second (WCAG 2.3.1)
- Optional: it is a separate component, so projects that do not add it carry none of its code
- Moving content can be stopped: by isPaused, by the Pause button, and by anything inside rdm-still
- Only the first copy of each row is in the accessibility tree; repeats are aria-hidden
- Reduced motion gives static rows that can be scrolled by hand, with the repeats removed
Guidelines
Use it when
- Large decorative words between page sections
Avoid it when
- Content people must read closely
- Navigation
Don't
- Essential information in a moving row
- Very high velocity factors
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-color-text-default--rd-color-border-default--rd-color-surface-default--rd-radius-control