Split Text Component
Splits a line of text into characters, words, or lines and reveals the pieces with a staggered animation — on mount or when it scrolls into view. Built on GSAP's SplitText and ScrollTrigger for accurate masking and resize-safe line splitting.
Features
- Split by
chars,words, orlines, each masked so pieces reveal from behind an edge. - Play on mount or on scroll into view via
scrollTriggerwith a configurablestart. - Fully overridable motion through
animationProps(GSAP tween vars). autoSplitre-splits on resize so line breaks stay correct.- Respects
prefers-reduced-motion— shows the final text with no animation.
Text that reveals itself, one word at a time.
Playground
Change what the text splits into and tune the motion, then replay.
Split and reveal your text with GSAP.
Installation
Usage
Notes & caveats
- Wrap your text in a single element.
childrenmust be one element (e.g. an<h2>or<p>) — the component splits its first child. A raw string or multiple siblings won't animate (a dev-only warning is logged). linesneeds a block element with a width. Line splitting is only meaningful when the text wraps, so give the wrapper a width (e.g.max-w-md); on an inline or shrink-wrapped element every "line" collapses into one.charsis best for short, Latin text. Character splitting breaks emoji and complex scripts (Arabic, Indic, ligatures), and on long text thestagger × counttotal gets very long. Preferwordsorlinesthere.- Font loading is handled for you. The split waits for
document.fonts.ready, so line breaks and masks measure against the real font — no need to enableautoSplitjust for that. - Reduced motion. With
prefers-reduced-motion, the text is shown immediately with no animation.
Props
| Property | Type | Default | Description |
|---|---|---|---|
children | ReactNode | required | A single text element (e.g. a heading or paragraph) to split and animate. |
className | string | — | Additional CSS classes for the wrapper. |
variant | SplitUnit | "words" | Which unit the text is split into and animated. |
mask | boolean | true | Mask each split piece (clip it) so it reveals from behind an edge instead of animating in fully visible. Masks by the same unit set in `variant`. |
animationProps | gsap.TweenVars | { yPercent: 120, rotate: 5, stagger: 0.2, duration: 0.4 } | GSAP tween vars merged over the defaults, e.g. `{ duration: 1.2 }`. |
scrollTrigger | boolean | false | Play the animation when the element scrolls into view instead of on mount. |
start | string | "top 85%" | ScrollTrigger start position (only used when `scrollTrigger` is true). |
autoSplit | boolean | false | Re-split on resize so line breaks stay correct. Note: this replays the animation on every resize, so it suits looping reveals more than one-shot entrances. Font-load correctness is handled automatically either way. |
markers | boolean | false | Show ScrollTrigger debug markers. |