Overview
The core splitText() function provides framework-agnostic text splitting with automatic kerning compensation. Use it with Motion, GSAP, CSS animations, or any animation library.
import { splitText } from "griffo" ;
Bundle size: 7.11 kB (minified + brotli)
Basic Usage
import { splitText } from "griffo" ;
import { animate , stagger } from "motion" ;
const { chars } = splitText ( document . querySelector ( "h1" ), { type: "chars" });
animate ( chars , { opacity: [ 0 , 1 ], y: [ 20 , 0 ] }, { delay: stagger ( 0.02 ) });
Split Types
Combine multiple split types with comma-separated values:
Characters Only
Words Only
Lines Only
Combined
const { chars } = splitText ( element , { type: "chars" });
// Returns: { chars: HTMLSpanElement[], words: [], lines: [] }
When splitting by chars, word wrappers are created internally for proper spacing even if type: "chars" is specified.
Masking for Reveal Animations
Wrap elements in overflow containers for clip-based reveals:
Line Masking
Word Masking
Char Masking
const { lines } = splitText ( element , {
type: "lines" ,
mask: "lines" ,
});
animate ( lines , { y: [ "100%" , "0%" ] }, { delay: stagger ( 0.1 ) });
Masking wraps each element in a <span> with overflow: clip for clean slide-in/out animations.
Auto Re-split on Resize
Automatically re-split text when the container resizes:
const result = splitText ( element , {
type: "words,lines" ,
autoSplit: true ,
onResplit : ({ words , lines }) => {
// Re-animate after resize
animate ( words , { opacity: [ 0 , 1 ] }, { delay: stagger ( 0.03 ) });
},
});
autoSplit requires the element to have a parent in the DOM. It observes the parent’s width and triggers a full re-split when changed.
Debouncing
Control the debounce delay for resize events:
splitText ( element , {
autoSplit: true ,
resplitDebounceMs: 200 , // Default: 100ms
onResplit : ({ words }) => {
console . log ( "Re-split triggered" );
},
});
Revert and Cleanup
Restore the original HTML and cleanup observers:
const { chars , revert } = splitText ( element , { type: "chars" });
animate ( chars , { opacity: [ 0 , 1 ] }). finished . then (() => {
revert (); // Restores original HTML
});
Auto-revert on Complete
splitText ( element , {
type: "words" ,
revertOnComplete: true ,
onSplit : ({ words }) => {
return animate ( words , { opacity: [ 0 , 1 ] }); // Auto-reverts when finished
},
});
revertOnComplete works with Motion animations (.finished), GSAP timelines (.then()), and raw Promises.
Custom Classes and Indexes
const { chars , words , lines } = splitText ( element , {
type: "chars,words,lines" ,
charClass: "my-char" ,
wordClass: "my-word" ,
lineClass: "my-line" ,
propIndex: true , // Adds CSS custom properties
});
CSS Custom Properties
When propIndex: true, each element gets:
/* Character span */
.my-char {
--char-index : 0 ;
}
/* Word span */
.my-word {
--word-index : 0 ;
}
/* Line span */
.my-line {
--line-index : 0 ;
}
Use in CSS animations:
@keyframes fadeIn {
from {
opacity : 0 ;
transform : translateY ( 20 px );
}
}
.my-char {
animation : fadeIn 0.5 s calc ( var ( --char-index ) * 0.02 s ) both ;
}
Initial Styles
Apply styles immediately after split:
splitText ( element , {
type: "words" ,
initialStyles: {
words: {
opacity: 0 ,
transform: "translateY(20px)" ,
},
},
onSplit : ({ words }) => {
animate ( words , { opacity: 1 , y: 0 }, { delay: stagger ( 0.05 ) });
},
});
Function-based Styles
splitText ( element , {
type: "chars" ,
initialStyles: {
chars : ( el , index ) => ({
opacity: 0 ,
transform: `translateY( ${ 20 + index * 5 } px)` ,
}),
},
});
Font Loading
Critical: Always wait for fonts before splitting to ensure accurate measurements.
// Recommended: Wait for fonts
document . fonts . ready . then (() => {
const { words } = splitText ( element , { type: "words" });
animate ( words , { opacity: [ 0 , 1 ] });
});
React and Motion components handle this automatically via waitForFonts prop (enabled by default).
Advanced: Lifecycle Callbacks
const result = splitText ( element , {
type: "chars,words,lines" ,
onSplit : ({ chars , words , lines }) => {
// Called immediately after split
console . log ( `Split ${ chars . length } chars into ${ lines . length } lines` );
// Return animation for revertOnComplete support
return animate ( chars , { opacity: [ 0 , 1 ] });
},
autoSplit: true ,
onResplit : ({ chars , lines }) => {
// Called when autoSplit triggers
console . log ( `Re-split into ${ lines . length } lines` );
},
revertOnComplete: true ,
});
Full API Reference
The HTML element containing text to split
options.type
string
default: "chars,words,lines"
Split types: "chars", "words", "lines", or comma-separated combinations
options.mask
'lines' | 'words' | 'chars'
Wrap elements in overflow containers for reveal animations
Automatically re-split on container resize
options.resplitDebounceMs
Debounce delay for autoSplit in milliseconds
Auto-revert when onSplit animation completes
Add CSS custom properties (--char-index, --word-index, --line-index)
Callback after split. Return animation for revertOnComplete.
Callback when autoSplit triggers
Apply styles after split. Supports static objects or functions.
options.charClass
string
default: "split-char"
Class name for character spans
options.wordClass
string
default: "split-word"
Class name for word spans
options.lineClass
string
default: "split-line"
Class name for line spans
Return Value
interface SplitTextResult {
chars : HTMLSpanElement [];
words : HTMLSpanElement [];
lines : HTMLSpanElement [];
revert : () => void ;
}
React Use SplitText with React lifecycle
Motion Declarative animations with Motion
Kerning How kerning compensation works
Performance Optimization tips