Vertical Cut Reveal
A text component that reveals the text with a cut reveal effect.
Source code
Understanding the component
-
First, the text is split into smaller pieces based on the
splitBy
prop: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
-
Each piece of text is wrapped in two
<span>
elements:- An outer
<span>
that acts as a container with its position toprelative
and its overflow tooverflow-hidden
- An inner
<span>
that holds the actual text, initially positioned off-screen usingy: 100
(or-100
ifreverse
is true)
- An outer
-
When the animation starts:
- The inner
<span>
elements smoothly transition from their off-screen position (y: 100
) to their final position (y: 0
) - This creates a "cutting" or "revealing" effect as each piece of text slides into view
- The animation can be staggered from different directions (first, last, center, or random) using the
staggerFrom
prop
- The inner
A key implementation detail is that the component always maintains word boundaries, even when splitting by characters. There are two reason for this:
- 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).
- 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.
staggerFrom variations
With the staggerFrom
prop, you can control the starting index of the animation. It can be either first
, last
, center
, a number
(custom index).
Or you can use the random
option, which will animate the elements in a random order. You can see the multiline text in action here too:
No auto start
If you don't want the animation to start automatically, you can set the autoStart
prop to false
. In this case, you can call the startAnimation
method exposed via a ref to start the animation manually. Here is an example demonstrating how to do this when the component is inside the viewport (with the useInView
hook from framer motion):
Notes
Since each element is "cutted" because of the overflow-hidden
property, with some fonts and font-families (eg italic), parts of the letter may be cutoff. That's why you can use the containerClassName
prop to style the container element, the worldLeterLevelClassName
prop to style word level container, and the elementLevelClassName
prop to style the individual split elements. You can add padding for example to accomodate more space for the text.
Props
Prop | Type | Default | Description |
---|---|---|---|
children* | string | - | The text to be displayed and animated |
reverse | boolean | true | Direction of the animation (true: bottom to top, false: top to bottom) |
transition | DynamicAnimationOptions | { type: "spring", damping: 30, stiffness: 300 } | Animation configuration for each element. Refer to framer-motion docs for more details |
splitBy | "words" | "characters" | "lines" | string | "words" | The split method for the text |
staggerDuration | number | 0.2 | Delay between each element's animation start |
staggerFrom | "first" | "last" | "center" | "random" | number | "first" | Starting index of the animation |
containerClassName | string | - | Additional CSS classes for styling the container |
wordLevelClassName | string | - | Additional CSS classes for styling the word level container |
elementLevelClassName | string | - | Additional CSS classes for styling the individual elements |
onClick | () => void | - | Callback function for click events |
onStart | () => void | - | Callback function for when the animation starts |
onComplete | () => void | - | Callback function for when the animation completes |
autoStart | boolean | true | Whether to start the animation automatically |