Examples

Examples


Landing Page Animations

Dynamic

Include the initial text in every string, and the static part will only be typed out once.


<TypeAnimation
  sequence={[
    // Same substring at the start will only be typed once, initially
    'We produce food for Mice',
    1000,
    'We produce food for Hamsters',
    1000,
    'We produce food for Guinea Pigs',
    1000,
    'We produce food for Chinchillas',
    1000,
  ]}
  speed={50}
  style={{ fontSize: '2em' }}
  repeat={Infinity}
/>
💡

Note: Typing complex characters like emojis requires a custom splitter function.

Initially Pre-rendered

By using the preRenderFirstString prop, you can initially (pre-)render the very first string of your sequence. When used with SSR (Next.js or similar), the initial string will be included in the static HTML, which may benefit SEO.


We produce food for Mice
<div>
  <TypeAnimation
    preRenderFirstString={true}
    sequence={[
      500,
      'We produce food for Mice', // initially rendered starting point
      1000,
      'We produce food for Hamsters',
      1000,
      'We produce food for Guinea Pigs',
      1000,
      'We produce food for Chinchillas',
      500,
    ]}
    speed={50}
    style={{ fontSize: '2em' }}
    repeat={Infinity}
  />
</div>

Continuation


<TypeAnimation
  sequence={[
    'One',
    500,
    'One Two', //  Continuing previous Text
    500,
    'One Two Three',
    500,
    'One Two',
    500,
    'One',
    500,
    '',
    500,
  ]}
  style={{ fontSize: '2em' }}
  repeat={Infinity}
/>

Replacement


<TypeAnimation
  sequence={['One', 500, 'Two', 500, 'Three', 500]}
  style={{ fontSize: '2em' }}
  repeat={Infinity}
/>

Custom Speed

As mentioned in the props section, you can specify both the typing speed and deletionSpeed with a simple relative number between 1-99 or an exactly specified keystroke delay.


speed={75}
speed={40} (default)
speed={{type: 'keyStrokeDelayInMs', value: 250}}
deletionSpeed={90}
omitDeletionAnimation={true}
💡

Note: The animation adds a random delay relative to your provided speed and deletionSpeed after each keystroke to make the typing animation look more natural.


Multiple Lines

By addding the white-space: pre-line css style and placing '\n' anywhere in your text, or making actual line breaks inside a string literal, you can write in multiple lines.


<TypeAnimation
  style={{ whiteSpace: 'pre-line', height: '195px', display: 'block' }}
  sequence={[
    `Line one\nLine Two\nLine Three\nLine Four\nLine Five
    
Line Seven`, // actual line-break inside string literal also gets animated in new line, but ensure there are no leading spaces
    1000,
    '',
  ]}
  repeat={Infinity}
/>
⚠️

Using the explicit \n new-line is preferred, because your code formatter may add spaces in new lines of the string literal that will be typed out as an empty string and hence unintentionally delay the animation.

💡

Pre-define the height and width of the parent element to prevent layout shift when typing multi-lines


Callback Functions

Use callback functions at any place inside of your animation sequence to perform any (global) actions you want. An exemplary use-case for this is calling functions or state updates that manipulate the styles of your animation component, or let your application know at which state of typing the animation currently is, and adjusting some other visual elements accordingly.


typingStatus: Initializing
const [typingStatus, setTypingStatus] = useState('Initializing');
 
<TypeAnimation
  sequence={[
    1500,
    () => {
      setTypingStatus('Typing...');
    },
    'Use callback-functions to trigger events',
    () => {
      setTypingStatus('Done Typing');
    },
    1000,
    () => {
      setTypingStatus('Deleting...');
    },
    '',
    () => {
      setTypingStatus('Done Deleting');
    },
  ]}
  repeat={Infinity}
/>;

Manipulation via CSS Classes

It's possible to manipulate the animation styles in order to, for example, stop the cursor animation at a specific point within the animation sequence:


const CURSOR_CLASS_NAME = 'custom-type-animation-cursor';
 
return (
  <>
    <TypeAnimation
      cursor={false}
      style={{
        fontSize: '1.75rem',
      }}
      className={CURSOR_CLASS_NAME}
      sequence={[
        'One',
        800,
        'One Two',
        800,
        'One Two Three',
        (el) => el.classList.remove(CURSOR_CLASS_NAME), // A reference to the element gets passed as the first argument of a callback function
        6000,
        (el) => el.classList.add(CURSOR_CLASS_NAME),
        '',
      ]}
      repeat={Infinity}
    />
 
    <style global jsx>{`
      .custom-type-animation-cursor::after {
        content: '|';
        animation: cursor 1.1s infinite step-start;
      }
      @keyframes cursor {
        50% {
          opacity: 0;
        }
      }
    `}</style>
  </>
);

Manipulation via State

By applying dynamic styles to the parent element of the TypeAnimation component, you can easily manipulate styles without classNames and passing ref.


const [textColor, setTextColor] = useState('red');
 
return (
  <>
    <div
      style={{
        fontSize: '35px',
        color: textColor,
        /* when working without ref and classNames, the manipulated style needs to be
         applied to the parent element, because the TypeAnimation component is perma-memoized */
      }}
    >
      <TypeAnimation
        sequence={[
          'One',
          800,
          () => setTextColor('aqua'),
          'One Two',
          800,
          () => setTextColor('deeppink'),
          'One Two Three',
          1000,
          () => setTextColor('darkkhaki'),
          '',
        ]}
        repeat={Infinity}
      />
    </div>
    <button
      onClick={() => {
        const items = [
          'blue',
          'green',
          'purple',
          'pink',
          'brown',
          'darkmagenta',
          'darksalmon',
          'dodgerblue',
          'firebrick',
          'darkviolet',
        ];
        setTextColor(items[Math.floor(Math.random() * items.length)]); // set random color
      }}
    >
      Change Color
    </button>
  </>
);

Custom String Splitter

By default, strings placed inside the sequence are split character by character, to simulate keyboard-like typing. With he help of the splitter prop, it's possible to define a custom splitting of sequence strings.

Typing Word by Word

To create a word-level typing animation similar to ChatGPT or other AI chatbots, we can split strings into single words, rather than characters.

   <TypeAnimation
        splitter={(str) => str.split(/(?= )/)} // 'Lorem ipsum dolor' -> ['Lorem', ' ipsum', ' dolor']
        sequence={[
          'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
          3000,
          '',
        ]}
        speed={{ type: 'keyStrokeDelayInMs', value: 30 }}
        omitDeletionAnimation={true}
        style={{ fontSize: '1em', display: 'block', minHeight: '200px' }}
        repeat={Infinity}
      />

Typing Complex Characters

As certain complex Unicode characters, like emojis, are internally represented as multiple characters in JavaScript, including them in our animation requires an advanced string splitter, such as grapheme-splitter (opens in a new tab), capable of splitting those characters into extended grapheme clusters (single letters).

import GraphemeSplitter from 'grapheme-splitter'; // npm i grapheme-splitter
 
const splitter = new GraphemeSplitter();
 
return (
  <TypeAnimation
        splitter={(str) => splitter.splitGraphemes(str)}
        sequence={[
          'Hello 🇬🇧',
          2000,
          'Ciao 🇮🇹',
          2000,
          '你好 🇨🇳',
          2000,
          'Здравейте 🇧🇬 ',
          2000,
          'Hola 🇪🇸',
          2000,
          'Bonjour 🇫🇷',
          2000,
          'नमस्ते 🇮🇳',
          2000
        ]}
        style={{ fontSize: '2em' }}
        repeat={Infinity}
      />
);