A small terminal window types a command, prints two lines of output, then drops to a fresh prompt with a blinking block cursor. The command types with steps() in ch units.
Also known as: terminal text animation css, command line typing animation, fake terminal window.
npm create app
Scaffolding ./app ...
✓ Done in 1.2s
<div class="txt-terminal-typing-effect">
<div class="txt-terminal-typing-effect-bar" aria-hidden="true"><i></i><i></i><i></i></div>
<div class="txt-terminal-typing-effect-body">
<p class="txt-terminal-typing-effect-cmd"><span class="txt-terminal-typing-effect-typed">npm create app</span><span class="txt-terminal-typing-effect-caret" aria-hidden="true"></span></p>
<p class="txt-terminal-typing-effect-out" style="--t: 2.1s">Scaffolding ./app ...</p>
<p class="txt-terminal-typing-effect-out" style="--t: 2.6s"><b>✓</b> Done in 1.2s</p>
<p class="txt-terminal-typing-effect-cmd txt-terminal-typing-effect-out" style="--t: 3s"><span class="txt-terminal-typing-effect-caret" aria-hidden="true"></span></p>
</div>
</div>.txt-terminal-typing-effect {
--c: var(--txt-color, #3b82f6);
font-size: var(--txt-size, 32px);
font-family: system-ui, sans-serif;
font-weight: 700;
line-height: 1.2;
display: inline-block;
width: 11em;
overflow: hidden;
border-radius: 0.35em;
background: #0d1117;
color: #e6edf3;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-weight: 500;
text-align: left;
box-shadow: 0 0 0 1px color-mix(in srgb, var(--c) 35%, #30363d), 0 0.3em 0.8em -0.3em rgb(0 0 0 / 0.4);}
.txt-terminal-typing-effect-bar {
display: flex;
gap: 0.16em;
padding: 0.28em 0.32em;
background: #161b22;
}
.txt-terminal-typing-effect-bar i {
width: 0.2em;
height: 0.2em;
border-radius: 50%;
background: #ff5f57;
}
.txt-terminal-typing-effect-bar i:nth-child(2) { background: #febc2e; }
.txt-terminal-typing-effect-bar i:nth-child(3) { background: #28c840; }
.txt-terminal-typing-effect-body {
padding: 0.7em 0.9em 0.9em;
font-size: 0.5em;
line-height: 1.6;
}
.txt-terminal-typing-effect-body p {
margin: 0;
white-space: nowrap;
}
.txt-terminal-typing-effect-cmd::before {
content: "$ ";
color: var(--c);
}
.txt-terminal-typing-effect-typed {
display: inline-block;
vertical-align: top;
overflow: hidden;
width: 0;
/* 14 = characters in the command */
animation: txt-terminal-typing-effect-type 1.3s steps(14) 0.5s forwards;
}
.txt-terminal-typing-effect-caret {
display: inline-block;
vertical-align: top;
width: 1ch;
height: 1.25em;
margin-top: 0.18em;
background: var(--c);
/* blinks, stays solid while typing, then hands over to the next prompt */
animation: txt-terminal-typing-effect-hold 2.1s step-end forwards;
}
.txt-terminal-typing-effect-out {
opacity: 0;
color: #8b949e;
animation: txt-terminal-typing-effect-print 0s var(--t) forwards;
}
.txt-terminal-typing-effect-out b {
color: var(--c);
font-weight: inherit;
}
.txt-terminal-typing-effect-out .txt-terminal-typing-effect-caret {
animation: txt-terminal-typing-effect-blink 1s step-end infinite;
}
/* 99.9% as well as 100%: a stepped animation squeezed to near-zero length
(reduced motion) can stop one step short of 100% */
@keyframes txt-terminal-typing-effect-type {
99.9%, to { width: 14ch; }
}
@keyframes txt-terminal-typing-effect-hold {
0%, 24% { opacity: 1; }
12%, 90%, 100% { opacity: 0; }
}
@keyframes txt-terminal-typing-effect-print {
to { opacity: 1; }
}
@keyframes txt-terminal-typing-effect-blink {
50% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
.txt-terminal-typing-effect, .txt-terminal-typing-effect *, .txt-terminal-typing-effect::before, .txt-terminal-typing-effect::after, .txt-terminal-typing-effect *::before, .txt-terminal-typing-effect *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--txt-color on the element or a parent.
Currently previewing #3b82f6.--txt-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 40px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.