
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Text splitting that keeps kerning intact.
Split text into characters, words, and lines for animation — without breaking your typography. Most splitting libraries wrap each character in a <span> and call it done, but that destroys the kerning between character pairs. Fetta compensates for this automatically.
Docs: https://fetta.dimi.me/
npm install fetta
import { splitText } from "fetta";
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) });
import { SplitText } from "fetta/react";
import { animate, stagger } from "motion";
<SplitText
options={{ type: "words" }}
onSplit={({ words }) => {
animate(words, { opacity: [0, 1], y: [20, 0] }, { delay: stagger(0.05) });
}}
>
<h1>Hello World</h1>
</SplitText>
import { SplitText } from "fetta/motion";
import { stagger } from "motion";
<SplitText
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.65, delay: stagger(0.04) }}
options={{ type: "words" }}
>
<h1>Hello World</h1>
</SplitText>
import { MorphText } from "fetta/morph";
<MorphText>{text}</MorphText>
<a>, <em>, <strong> and other inline elements with all attributes| Import | Use for | Size |
|---|---|---|
fetta | Vanilla JS or any framework | 7.11 kB |
fetta/react | React with callback/lifecycle control | 8.23 kB |
fetta/motion | Declarative Motion animations | 13.78 kB |
fetta/morph | Standalone MorphText component | 7.95 kB |
Sizes are minified + brotli.
Full API reference at fetta.dimi.me. Summary below.
splitText(element, options?) — Core docsReturns { chars, words, lines, revert }. Key options: type, mask, autoSplit, onSplit, revertOnComplete, initialStyles, propIndex.
import { splitText } from "fetta";
import { animate, stagger } from "motion";
document.fonts.ready.then(() => {
const { words } = splitText(element, { type: "words", mask: "words" });
animate(words, { y: ["100%", "0%"] }, { delay: stagger(0.1) });
});
<SplitText> — React docsWraps splitText() with React lifecycle, viewport callbacks, and automatic cleanup. Key props: onSplit, onResplit, options, autoSplit, waitForFonts, revertOnComplete, viewport, onViewportEnter, initialStyles.
import { SplitText } from "fetta/react";
import { animate, stagger } from "motion";
<SplitText
options={{ type: "words" }}
initialStyles={{ words: { opacity: 0, transform: "translateY(20px)" } }}
viewport={{ amount: 0.5 }}
onViewportEnter={({ words }) =>
animate(words, { opacity: 1, y: 0 }, { delay: stagger(0.05) })
}
resetOnViewportLeave
>
<p>Animates when scrolled into view</p>
</SplitText>
<SplitText> — Motion docsIncludes all React props plus Motion animation: variants, initial, animate, exit, whileInView, whileScroll, whileHover, whileTap, whileFocus, transition, delayScope, custom. Supports flat targets, per-type targets (chars/words/lines/wrapper), and function variants.
import { SplitText } from "fetta/motion";
import { stagger } from "motion";
<SplitText
variants={{
hidden: { chars: { opacity: 0, y: 10 } },
visible: {
chars: ({ lineIndex }) => ({
opacity: 1,
y: 0,
transition: {
delay: stagger(0.02, { startDelay: lineIndex * 0.15 }),
},
}),
},
}}
initial="hidden"
animate="visible"
options={{ type: "chars,lines", mask: "lines" }}
>
<p>Per-line staggered reveal</p>
</SplitText>
<MorphText> — Morph docsText morphing with stable token identity. Matching tokens interpolate position, new tokens enter, removed tokens exit. Supports splitBy="chars" (default) and splitBy="words". The initial, animate, and exit props accept static targets or ({ index, count }) => Target callbacks.
import { MorphText } from "fetta/morph";
<MorphText
splitBy="words"
initial={({ index, count }) => ({
opacity: 0,
x: index <= count / 2 ? -75 : 75,
})}
animate={{ opacity: 1, x: 0 }}
>
{statusText}
</MorphText>
createSplitClones() — Helpers docsCreates clone layers from split output for reveal/swap effects. Pass an existing splitText() result.
import { splitText } from "fetta";
import { createSplitClones } from "fetta/helpers";
const split = splitText(element, { type: "chars", mask: "chars" });
const layers = createSplitClones(split, { unit: "chars", wrap: true });
// animate layers.originals + layers.clones...
layers.cleanup();
font-variant-ligatures: none) because ligatures can't span multiple elements.waitForFonts). In vanilla, wrap calls in document.fonts.ready.aria-label, generic elements get a screen-reader-only copy.If you find Fetta useful, consider sponsoring the project to support continued development.
MIT
FAQs
Text splitting library with kerning compensation for animations
We found that fetta demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.