Large text that shows a video you supply through its letters. The text stays real text; a gradient fallback shows until the video plays.
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.
import { VideoText } from "@rdloom/react";
// A public sample video (CC0) shows through the letters. Pass your own src. Until it loads, or for reduced motion,
// the letters show a gradient.
export default function VideoTextBasicExample() {
return (
<div className="flex w-full justify-center py-6">
<VideoText src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4" className="px-4 text-8xl font-bold sm:text-9xl">Motion</VideoText>
</div>
);
}Installation
npx rdloom add video-textCopies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes.
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/video-text.jsonWorks, but without upgrade tracking, and you import the motion CSS yourself.
Usage
import { VideoText } from "@rdloom/react";
<div className="flex w-full justify-center py-6">
<VideoText src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4" className="px-4 text-8xl font-bold sm:text-9xl">Motion</VideoText>
</div>Dark
import { VideoText } from "@rdloom/react";
export default function VideoTextDarkExample() {
return (
<div className="flex w-full justify-center bg-black py-6">
<VideoText tone="dark" src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4" fallback="linear-gradient(90deg, #f472b6, #facc15)" className="px-4 text-8xl font-bold sm:text-9xl">
Night
</VideoText>
</div>
);
}Paused
import { VideoText } from "@rdloom/react";
export default function VideoTextPausedExample() {
return (
<div className="flex w-full justify-center py-6">
<VideoText isPaused src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4" className="px-4 text-8xl font-bold sm:text-9xl">
Still
</VideoText>
</div>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
childrenrequiredThe text. | string | none |
srcURL of the video you supply. Without it the fallback gradient is shown. | string | none |
posterURL of a poster image for the video. | string | none |
fallbackCSS background shown through the letters until the video plays, or instead of it. | string | "linear-gradient(120deg, var(--rd-color-action-primary), var(--rd-color-feedback-info))" |
toneThe surface the video box sits on: light draws a white box, dark a black one. | "light" | "dark" | "light" |
isPausedPauses the video and shows the fallback gradient instead. 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
- Read as ordinary text: the effect is purely visual
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
- No video is included: you supply src. The video is muted, plays inline, loops and is hidden from assistive technology
- Until the video has loaded, and whenever it is paused, stopped by reduced motion or unavailable, the letters show the fallback gradient
- A video behind letters has no guaranteed contrast: keep the text large and bold, and do not use it for text people must read to act
- Decorative video needs no captions; if the video carries meaning, give that meaning in nearby text
Guidelines
Use it when
- A large hero word over a short looping video
Avoid it when
- Small text
- Text people must read to act
- Slow connections where the video is large
Don't
- Autoplaying video with sound
- Long videos with fast cuts or flashing
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-color-text-default--rd-color-action-primary--rd-color-feedback-info