Dev

React Stagger Text

A React component for creating staggered text animations.

You like staggered text animations?

Well then, good news! I just released StaggerText, a React component for creating text animations that stagger word-by-word or letter-by-letter.

📌 Features

  • Built in Typescript
  • Wraps words or letters inside spans so we can sequentially fade in each span.
  • Animations use CSS transitions.
  • Animations are triggered when text is in the viewport, via Intersection Observer
  • Options exist for animation start, start delay, and stagger duration, delay, and easing.
  • Callback for when animation is complete

To see it in action and discover the available props/options, check the Demo / Docs site.

Or, take a peek at the code at the repo on Github.

đŸŽ¯ Quickstart

Install (via npm)

npm i react-stagger-text

Use that thing

import StaggerText from "react-stagger-text"
 
function SomeComponent() {
  return (
    <h1>
      <StaggerText>
        This text will be staggered by word
      </StaggerText>
    </h1>
  )
}

đŸ•šī¸ Usage

Stagger by letter

<StaggerText
  staggerType='letter'
  staggerDuration={0.4}
  startDelay={0.04}
>
 Let's go ahead and stagger this by letter.
</StaggerText>

Callback when stagger completes

const handleStaggerEnd = () => {
  console.log('sup ya'll, i'm dun')
}
 
<StaggerText
  onStaggerComplete={handleStaggerEnd}
>
  Stagger this text, then let em know
</StaggerText>

Sequentially stagger multiple instances

If you'd like to dynamically chain multiple instances, meaning, begin one instance of <StaggerText> after an other <StaggerText> completes, you can leverage the component's callback and shouldStart prop:

First, Create an array of objects to house you titles and options.

// Some data with titles and config
const lines = [
  {
    title: "Stagger this first line by word",
    staggerType: "word",
    staggerDelay: 0.09,
    staggerDuration: 0.7
  },
  {
    title: "And, stagger this line by letter after the first.",
    staggerType: "letter",
    staggerDelay: 0.04,
    staggerDuration: 0.4,
    startDelay: 300
  }
  // etc
]

Then, setup state to monitor the current index, loop over your data, and use the onStaggerComplete callback to update the shouldStart flag to true based on currentIndex.

// Component
import { useState } from 'react'
 
const StaggeredTextLines: React.FC<Props> = (lines) => {
  const [currentIndex, setCurrentIndex] = useState(0)
 
  // Callback handler
  const handleStaggerComplete = () => {
    setCurrentIndex((prevIndex) => prevIndex + 1)
  }
 
  return (
    {lines.map((line, index) => (
      <StaggerText
        key={index}
        onStaggerComplete={
          index === currentIndex ? handleStaggerComplete : null
        }
        shouldStart={index === currentIndex}
        startDelay={line.startDelay}
        staggerType={line.staggerType}
        staggerDuration={line.staggerDuration}
        staggerDelay={line.staggerDelay}
      >
        {line.title}
      </StaggerText>
    }
  )
}

📓 Notes

For smoother, less choppy transitions, favor longer staggerDuration and shorter staggerDelay. For example, StaggerDuration={0.7} StaggerDelay={0.09} provides a nice smooth effect by word. For letters, StaggerDuration={0.5} StaggerDelay={0.04} returns a smooth transition.

📅 ToDos

  • ~~Add callback for when stagger completes.~~
  • ~~Add option for controlling the start of stagger.~~
  • Maybe remove span wrappers from the DOM once stagger completes?
  • Maybe provide a method for restarting or even rewinding transitions?
  • Provide additional animation type that slices text into view via translateY.

To learn more about React Stagger Text, check out the docs. Have a feature idea or looking to contribute? Check out the Repo.