Skip to content

Text Animate

Text that animates in by character, word or line using a preset: fade in, blur in, slide up or scale up. The words are real text in the page from the start.

Motionv0.1.0experimentalWCAG 2.2 AAView spec

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.

Words that arrive one at a time
import { TextAnimate } from "@rdloom/react";

export default function TextAnimateBasicExample() {
  return (
    <div className="flex w-full justify-center">
      <TextAnimate className="text-2xl font-semibold">Words that arrive one at a time</TextAnimate>
    </div>
  );
}

Installation

npx rdloom add text-animate

Copies 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/text-animate.json

Works, but without upgrade tracking, and you import the motion CSS yourself.

Usage

import { TextAnimate } from "@rdloom/react";

<div className="flex w-full justify-center">
  <TextAnimate className="text-2xl font-semibold">Words that arrive one at a time</TextAnimate>
</div>

Presets

Fade inBlur inSlide upScale up
import { TextAnimate } from "@rdloom/react";

export default function TextAnimatePresetsExample() {
  return (
    <div className="flex w-full flex-col items-center gap-3 text-lg font-medium">
      <TextAnimate animation="fadeIn">Fade in</TextAnimate>
      <TextAnimate animation="blurIn" delay={0.2}>
        Blur in
      </TextAnimate>
      <TextAnimate animation="slideUp" delay={0.4}>
        Slide up
      </TextAnimate>
      <TextAnimate animation="scaleUp" delay={0.6}>
        Scale up
      </TextAnimate>
    </div>
  );
}

By character

Hello there
import { TextAnimate } from "@rdloom/react";

// Keep character animation to a few words: the total time grows with every letter.
export default function TextAnimateByCharacterExample() {
  return (
    <div className="flex w-full justify-center">
      <TextAnimate by="character" animation="slideUp" stagger={0.04} className="text-3xl font-bold">
        Hello there
      </TextAnimate>
    </div>
  );
}

API Reference

Defined by the spec. Components also accept the props of the React Aria component they wrap.

PropTypeDefault
childrenrequired

The text. In line mode, each new line (a newline character) is one unit.

stringnone
by

What is animated one after another.

"character" | "word" | "line""word"
animation

The preset each unit plays.

"fadeIn" | "blurIn" | "slideUp" | "scaleUp""fadeIn"
delay

Seconds before the first unit starts.

number0
duration

Seconds each unit takes.

number0.5
stagger

Seconds between one unit starting and the next.

number0.05
whenInView

Waits until the text scrolls into view before playing.

booleanfalse
isPaused

Stops the animation and shows the finished text. Moving content that lasts more than five seconds should be stoppable.

booleanfalse

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

  • The full text is read once; the animation is not announced

What your code must do

  • The full text is present as visually hidden text, so assistive technology reads it once and never character by character
  • The animated copy is hidden from assistive technology
  • With no JavaScript, or with reduced motion, the text is shown at once
  • 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
  • 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

Guidelines

Use it when

  • A heading or short intro that should arrive with some life
  • Staggering a short list of words

Avoid it when

  • Long passages, especially by character
  • Text that changes often

Don't

  • Animating by character on text that will be read aloud
  • A very long total time: delay plus stagger times the number of units should stay short

Design tokens

The semantic tokens this component uses. Change them once and every component follows; see Design tokens.

  • --rd-color-text-default
  • --rd-color-text-muted