Typewriter effect
Also called typing animation, typing effect, or typewriter text
A text animation that reveals a line one character at a time, as if someone were typing it, usually with a blinking caret at the end.
import { useEffect, useState } from 'react';
import { motion, useReducedMotion } from 'motion/react';
const PHRASES = [
'Build your app in minutes',
'Launch your store today',
'Ship your idea tonight'
];
const TYPE_MS = 50;
const DELETE_MS = 30;
const PAUSE_MS = 2000;
const BLINK = { duration: 1, times: [0, 0.5, 0.5, 1], repeat: Infinity };
export function TypewriterHeadline() {
const reduceMotion = useReducedMotion();
const [index, setIndex] = useState(0);
const [text, setText] = useState('');
const [deleting, setDeleting] = useState(false);
const phrase = PHRASES[index]!;
useEffect(() => {
if (reduceMotion) return;
const done = !deleting && text === phrase;
const timer = setTimeout(
() => {
if (done) setDeleting(true);
else if (deleting && text === '') {
setDeleting(false);
setIndex((index + 1) % PHRASES.length);
} else setText(phrase.slice(0, text.length + (deleting ? -1 : 1)));
},
done ? PAUSE_MS : deleting ? DELETE_MS : TYPE_MS
);
return () => clearTimeout(timer);
}, [reduceMotion, phrase, index, text, deleting]);
return (
<h1 className='text-4xl font-bold tracking-tight'>
<span className='sr-only'>{PHRASES[0]}</span>
{/* All phrases share one grid cell, so the longest reserves the width. */}
<span aria-hidden className='inline-grid'>
{PHRASES.map((p) => (
<span key={p} className='invisible [grid-area:1/1]'>
{p}
</span>
))}
<span className='[grid-area:1/1]'>
{reduceMotion ? PHRASES[0] : text}
{!reduceMotion && (
<motion.span
animate={{ opacity: [1, 1, 0, 0] }}
transition={BLINK}
className='ml-0.5 inline-block h-[1em] w-0.5 translate-y-[0.1em] bg-current'
/>
)}
</span>
</span>
</h1>
);
}Add a typewriter effect to the hero headline: type "Build your app in minutes" at 50ms per character with a blinking caret, pause for 2 seconds, delete it at 30ms per character, and type the next phrase in the list. Reserve the width of the longest phrase so nothing shifts, give screen readers the full text, and show the first phrase instantly when prefers-reduced-motion is set.
Paste into Layerwise or any AI coding tool.
What is Typewriter effect?
A typewriter effect adds the characters of a line one by one at a steady pace, with a caret (the text cursor) at the end. Many versions then delete the line and type the next phrase, so one headline can cycle through several ideas.
It suits hero headlines, chat-style intros, terminal looks, and search boxes that suggest example queries. Keep the lines short: at 50ms per character, a 40-character sentence takes two seconds to finish, and visitors rarely wait longer than that.
Reserve the width of the longest line so the layout does not jump as letters appear. Screen readers can announce every partial word, so give them the full text with an aria-label and hide the animated copy with aria-hidden. When someone prefers reduced motion, show the finished text right away.
Often confused with
- Text scramble
- A text scramble shows every character at once as random glyphs that settle into the real letters. A typewriter adds characters one at a time.
Related terms
All termsText scramble
A text animation where each character flickers through random letters and symbols before settling on the final word, like a code being cracked.
Rotating words
A headline where one word keeps changing in place, rolling or fading through a short list while the rest of the sentence stays put.
Stepped animation
An animation that jumps through a set number of frames instead of moving smoothly, made with the CSS steps() timing function.
Reduced motion
An operating system setting that asks apps to minimize movement, which websites detect with the prefers-reduced-motion media query.
Build it with Layerwise
Describe your app, watch it run in a live preview, and publish it with a database, storage, and sign-in built in.