Overview
The SplitTextResult interface defines the object returned by the splitText function. It contains arrays of split elements and a revert function to restore the original HTML.
Type Definition
interface SplitTextResult {
chars: HTMLSpanElement[];
words: HTMLSpanElement[];
lines: HTMLSpanElement[];
revert: () => void;
}
Properties
chars
Array of character span elements. Empty array if type option doesn’t include "chars".
Example:
const { chars } = splitText(element, { type: "chars" });
chars.forEach((char, index) => {
console.log(`Character ${index}: ${char.textContent}`);
});
Element Structure:
<span class="split-char" data-char-index="0" style="--char-index: 0">H</span>
<span class="split-char" data-char-index="1" style="--char-index: 1">e</span>
<span class="split-char" data-char-index="2" style="--char-index: 2">l</span>
<span class="split-char" data-char-index="3" style="--char-index: 3">l</span>
<span class="split-char" data-char-index="4" style="--char-index: 4">o</span>
words
Array of word span elements. Empty array if type option doesn’t include "words".
Example:
const { words } = splitText(element, { type: "words" });
words.forEach((word, index) => {
console.log(`Word ${index}: ${word.textContent}`);
});
Element Structure:
<span class="split-word" data-word-index="0" style="--word-index: 0">
<span class="split-char">H</span>
<span class="split-char">e</span>
<span class="split-char">l</span>
<span class="split-char">l</span>
<span class="split-char">o</span>
</span>
<span class="split-word" data-word-index="1" style="--word-index: 1">
<span class="split-char">W</span>
<span class="split-char">o</span>
<span class="split-char">r</span>
<span class="split-char">l</span>
<span class="split-char">d</span>
</span>
When splitting chars, word wrappers are always created internally for proper spacing, even if type doesn’t include "words". They are only returned in the words array if explicitly requested.
lines
Array of line span elements. Empty array if type option doesn’t include "lines".
Example:
const { lines } = splitText(element, { type: "lines" });
lines.forEach((line, index) => {
console.log(`Line ${index}: ${line.textContent}`);
});
Element Structure:
<span class="split-line" data-line-index="0" style="--line-index: 0">
<span class="split-word">...</span>
<span class="split-word">...</span>
</span>
<span class="split-line" data-line-index="1" style="--line-index: 1">
<span class="split-word">...</span>
<span class="split-word">...</span>
</span>
Line Detection:
Lines are detected automatically based on the vertical position of word elements. Lines wrap based on the container width and CSS properties like max-width.
revert
Function that reverts the element to its original HTML and cleans up all observers and timers.
Behavior:
- Restores the original innerHTML
- Restores the original
aria-label attribute (if applicable)
- Disconnects all ResizeObservers
- Clears all debounce timers
- Removes window resize listeners
- Keeps
font-variant-ligatures: none if chars were split (prevents visual shift)
- Automatically calls internal
dispose() to clean up resources
Example:
const result = splitText(element);
// Animate
animate(result.words, { opacity: [0, 1] }).finished.then(() => {
// Revert when animation completes
result.revert();
});
Auto-Revert:
Use revertOnComplete option for automatic reverting:
splitText(element, {
onSplit: ({ words }) => animate(words, { opacity: [0, 1] }),
revertOnComplete: true,
});
// Automatically reverts after animation completes
Usage Examples
Animating Characters
import { splitText } from "griffo";
import { animate, stagger } from "motion";
const { chars, revert } = splitText(element, { type: "chars" });
animate(
chars,
{ opacity: [0, 1], y: [20, 0] },
{ delay: stagger(0.05) }
).finished.then(() => {
revert();
});
Animating Words and Lines
const { words, lines } = splitText(element, { type: "words,lines" });
// Animate lines sliding up
animate(
lines,
{ opacity: [0, 1], y: [40, 0] },
{ delay: stagger(0.1) }
);
// Animate words within each line
words.forEach((word, index) => {
animate(
word,
{ opacity: [0, 1] },
{ delay: index * 0.02 }
);
});
Conditional Animation
const { chars, words, lines } = splitText(element, {
type: "chars,words,lines",
});
if (chars.length > 0) {
// Animate individual characters
animate(chars, { opacity: [0, 1] });
} else if (words.length > 0) {
// Fallback to word animation
animate(words, { opacity: [0, 1] });
}
Accessing Element Properties
const { chars } = splitText(element, {
type: "chars",
propIndex: true,
});
chars.forEach((char) => {
// Access CSS custom property
const index = char.style.getPropertyValue("--char-index");
// Access data attribute
const dataIndex = char.dataset.charIndex;
// Access position
const { top, left } = char.getBoundingClientRect();
console.log({ index, dataIndex, top, left });
});
Empty Arrays
Arrays are empty when the corresponding split type is not requested:
const result = splitText(element, { type: "words" });
console.log(result.chars.length); // 0 (chars not requested)
console.log(result.words.length); // > 0 (words requested)
console.log(result.lines.length); // 0 (lines not requested)
Type Guards
function animateIfAvailable(result: SplitTextResult) {
if (result.chars.length > 0) {
animate(result.chars, { opacity: [0, 1] });
}
if (result.words.length > 0) {
animate(result.words, { y: [20, 0] });
}
if (result.lines.length > 0) {
animate(result.lines, { x: [-40, 0] });
}
}
See Also