Docs
Text Rotate

Text Rotate

A text component that switches the rendered text from a list.

Make it work!

Installation


npx shadcn@latest add "https://fancycomponents.dev/r/text-rotate.json"

Understanding the component


  1. For the animation, we switch the actual rendered text from the texts array. Either automatically, if the auto prop is set to true, or we can do it manually, by calling the next() or previous() methods exposed via a ref.

  2. For animating out the previous text, and animating in the next, we use the AnimatePresence component from motion/react. The initial, animate and exit props can be used to define the three states of the text. Refer to the motion documentation for more details.

  3. The current text is split into smaller pieces based on the splitBy prop, which will determine how the text will be animated:

    • words: Splits into individual words (e.g., "Hello world" → ["Hello", "world"])
    • characters: Splits into individual characters (e.g., "Hi" → ["H", "i"])
    • lines: Splits by newline characters (\n)
    • string: Splits by any custom string delimiter
  4. Each piece of text is wrapped in two <span> elements: An outer <span> that acts as a container for a word or line of text and an inner <span> that holds the actual text. There are two reasons for this:

    1. When dealing with multi-line text, each line maintains its own reveal animation starting point. This means if you have text that spans multiple lines, each line will animate independently from its own baseline, rather than all elements animating from a single point (like the bottom of the entire paragraph).
    2. When using characters mode, characters from the same word stay together in a word container. This prevents unwanted line breaks in the middle of words - if a word needs to wrap to the next line, it will wrap as a complete unit rather than having some characters on one line and others on the next line. This maintains proper text flow and readability while still allowing character-by-character animation within each word.

Examples


SplitBy variations

With the splitBy prop, you can control how the text is split into smaller pieces. It can be either words, characters, lines, or a custom string delimiter. In case of lines, you are responsible for adding the \n delimiter yourself.

The following example demonstrates the words (the quote) and characters (the author) mode. It should respect multiline texts.

A typeface family is an accomplishment on the order of a novel, a feature film screenplay, a computer language design and implementation, a major musical composition, a monumental sculpture, or other artistic or technical endeavors that consume a year or more of intensive creative effort.
Charles Bigelow

Stagger

With the staggerFrom prop, you can control the index of the letter/word/line where the stagger animation starts. Possible values are "first", "center", "last", "random", or a number.

city
New YorkSão PauloTokyoMumbai

Manual control

If the auto prop is set to false, you can manually control the animation by calling the next() or previous() methods exposed via a ref.

this is the first text

This can be handy for a lot of use cases, eg. a scroll-triggered animation.

Branislav Rodman
Example 2
Example 3
Example 4
Example 5
Example 6
Example 7
Example 8

Notes


If you're using auto mode, make sure that the rotationInterval prop is set to a value that's greater than the duration of initial/exit animations, otherwise we will switch to a new text before the animation is complete.

Props


TextRotateProps

PropTypeDefaultDescription
texts*string[]-The text to be displayed and animated
initialMotionProps["initial"]{ y: "100%", opacity: 0 }Initial styles for the text
animateMotionProps["animate"]{ y: 0, opacity: 1 }Target styles for the text
exitMotionProps["exit"]{ y: "-120%", opacity: 0 }Styles for the text for animating out
animatePresenceModeAnimatePresenceProps["mode"]"wait"The mode for the AnimatePresence component. Refer to motion docs for more details
animatePresenceInitialbooleanfalseWhether to animate in the initial state for AnimatePresence. Refer to motion docs for more details
rotationIntervalnumber2000The interval in milliseconds between each rotation
transitionValueAnimationTransition{ type: "spring", damping: 25, stiffness: 300 }Animation configuration for each letter. Refer to motion docs for more details
staggerDurationnumber0Delay between each letter's animation start
staggerFrom"first" | "last" | "center" | "random" | number"first"Starting index of the stagger effect
loopbooleantrueWhether to loop through the texts
autobooleantrueWhether to start the animation automatically
splitBy"words" | "characters" | "lines" | string"words"The split method for the text
onNext(index: number) => void-Callback function for when the next text is rendered
mainClassNamestring-Additional CSS classes for styling the container
splitLevelClassNamestring-Additional CSS classes for styling the individual words or lines
elementLevelClassNamestring-Additional CSS classes for styling the individual characters/words/lines

TextRotateRef

MethodDescription
next()Goes to the next text
previous()Goes back to the previous text
jumpTo(index: number)Jumps to a specific text index
reset()Resets the animation to the initial state