Splitting Text

Text that comes in piece by piece, by character, word or line.

Splitting Text
"use client"

import * as React from "react"
import {
  SplittingText,
  type SplittingTextProps,
} from "@animate-ui/react/primitives/texts/splitting"
import { RefreshIcon } from "@hugeicons/core-free-icons"
import { HugeiconsIcon } from "@hugeicons/react"

import { Button } from "@/components/ui/button"

const ANIMATIONS = {
  default: {},
  vibe: {
    initial: { y: 50, scale: 0.5, opacity: 0, x: 50, rotate: 90 },
    animate: { y: 0, scale: 1, opacity: 1, x: 0, rotate: 0 },
    transition: { duration: 0.5, ease: "easeOut" },
  },
  writing: {
    initial: { y: 10, opacity: 0 },
    animate: { y: 0, opacity: 1 },
    transition: { type: "spring", bounce: 0, duration: 2 },
  },
} satisfies Record<
  string,
  Pick<SplittingTextProps, "initial" | "animate" | "transition">
>

export default function SplittingTextDemo({
  type = "chars",
  delay = 0,
  animation = "default",
}: {
  type?: "chars" | "words" | "lines"
  delay?: number
  animation?: keyof typeof ANIMATIONS
}) {
  const [run, setRun] = React.useState(0)
  const props = { delay, ...ANIMATIONS[animation] }

  return (
    <div className="flex flex-col items-center gap-6">
      {type === "lines" ? (
        <SplittingText
          key={`${run}-${type}-${delay}-${animation}`}
          className="text-xl font-semibold"
          type="lines"
          text={[
            "Introducing Splitting Text component",
            "Made with Motion. Highly customizable and easy to use.",
          ]}
          {...props}
        />
      ) : (
        <SplittingText
          key={`${run}-${type}-${delay}-${animation}`}
          className="text-4xl font-semibold"
          type={type}
          text="Splitting Text"
          {...props}
        />
      )}
      <Button variant="outline" size="sm" onClick={() => setRun((n) => n + 1)}>
        <HugeiconsIcon icon={RefreshIcon} strokeWidth={2} data-icon="inline-start" />
        Replay
      </Button>
    </div>
  )
}

Installation

npm install @animate-ui/react motion
pnpm add @animate-ui/react motion
yarn add @animate-ui/react motion
bun add @animate-ui/react motion

Usage

import { SplittingText } from '@animate-ui/react/primitives/texts/splitting';

export function Title() {
  return <SplittingText text="Splitting Text" type="words" inView />;
}

Pass an array of lines with type="lines":

<SplittingText
  type="lines"
  text={['Introducing Splitting Text', 'Made with Motion.']}
/>

Animation

  • Each piece fades in and slides 150px in from the right over 0.7s on an ease-out, 0.05s apart for characters, 0.2s for words, 0.3s for lines.
  • initial, animate and transition customise every piece.
  • Words never break in the middle; emoji and accented letters stay whole.
  • <AnimateUIProvider tempo> paces the default transition and stagger.
  • Under reduced motion (or with disableAnimation), every piece is in place at once.
  • Screen readers read the text once, not piece by piece.

API Reference

SplittingText

PropTypeDefault
text
string | string[]-
type?
'chars' | 'words' | 'lines''chars'
stagger?
number0.05 (chars), 0.2 (words), 0.3 (lines)
delay?
number0
initial?
TargetAndTransition{ x: 150, opacity: 0 }
animate?
TargetAndTransition{ x: 0, opacity: 1 }
transition?
Transition{ duration: 0.7, ease: 'easeOut' }
disableAnimation?
booleanfalse
inView?
booleanfalse
inViewMargin?
string'0px'
inViewOnce?
booleantrue
...props?
Omit<HTMLMotionProps<'div'>, 'children' | 'initial' | 'animate' | 'transition'>-

Built by Skyleen. The source code is available on GitHub.

Last updated: 10/18/2026

On this page