AI CSS Animations

Code Typing Animation

Three lines of syntax-colored JavaScript type into a small dark editor with line numbers, while the active-line highlight follows along. Colored tokens are spans inside each clipped line.

Also known as: code editor typing effect, typing code css, syntax highlighted typewriter.

const greet = (name) => "Hello, " + name; greet("world");

HTML

<div class="txt-code-typing-animation">
  <div class="txt-code-typing-animation-tab" aria-hidden="true">greet.js</div>
  <div class="txt-code-typing-animation-code">
    <span class="txt-code-typing-animation-ln" style="--n: 23; --d: 0.4s; --hold: 1.6s"><span class="txt-code-typing-animation-t"><span class="txt-code-typing-animation-k">const</span> <span class="txt-code-typing-animation-f">greet</span> = (name) =&gt;</span></span>
    <span class="txt-code-typing-animation-ln" style="--n: 17; --d: 2s; --hold: 1.3s">  <span class="txt-code-typing-animation-t"><span class="txt-code-typing-animation-s">"Hello, "</span> + name;</span></span>
    <span class="txt-code-typing-animation-ln" style="--n: 15; --d: 3.3s"><span class="txt-code-typing-animation-t"><span class="txt-code-typing-animation-f">greet</span>(<span class="txt-code-typing-animation-s">"world"</span>);</span></span>
  </div>
</div>

CSS

.txt-code-typing-animation {
  --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;
  overflow: hidden;
  border-radius: 0.3em;
  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) 30%, #30363d);}
.txt-code-typing-animation-tab {
  display: inline-block;
  padding: 0.35em 0.9em;
  font-size: 0.4em;
  color: #8b949e;
  background: #161b22;
  box-shadow: inset 0 0.12em 0 var(--c);
}
.txt-code-typing-animation-code {
  position: relative;
  box-sizing: content-box;
  /* gutter + the longest line, so the editor keeps its size while typing */
  width: calc(3.5ch + 23ch + 0.2em);
  padding: 0.6em 1.4em 0.7em 0;
  font-size: 0.5em;
  line-height: 1.7;
  counter-reset: txt-code-typing-animation-n;
}
/* the active-line highlight steps down as each line starts */
.txt-code-typing-animation-code::before {
  content: "";
  position: absolute;
  top: 0.6em;
  left: 0;
  right: 0;
  height: 1.7em;
  background: rgb(255 255 255 / 0.06);
  box-shadow: inset 0.15em 0 0 var(--c);
  animation: txt-code-typing-animation-row 3.3s step-end forwards;
}
.txt-code-typing-animation-ln {
  position: relative;
  display: block;
  white-space: pre;
}
.txt-code-typing-animation-ln::before {
  counter-increment: txt-code-typing-animation-n;
  content: counter(txt-code-typing-animation-n);
  display: inline-block;
  width: 2ch;
  margin-right: 1.5ch;
  text-align: right;
  color: #6e7681;
}
.txt-code-typing-animation-t {
  display: inline-block;
  vertical-align: top;
  box-sizing: content-box;
  width: 0;
  overflow: hidden;
  border-right: 0.12em solid transparent;
  animation:
    txt-code-typing-animation-type calc(var(--n) * 55ms) steps(var(--n)) var(--d) forwards,
    txt-code-typing-animation-caret var(--hold) step-end var(--d);
}
.txt-code-typing-animation-ln:last-child .txt-code-typing-animation-t {
  animation:
    txt-code-typing-animation-type calc(var(--n) * 55ms) steps(var(--n)) var(--d) forwards,
    txt-code-typing-animation-blink 1s step-end var(--d) infinite;
}
.txt-code-typing-animation-k { color: color-mix(in srgb, var(--c) 65%, #fff); }
.txt-code-typing-animation-f { color: #d2a8ff; }
.txt-code-typing-animation-s { color: #7ee787; }
@keyframes txt-code-typing-animation-type {
  99.9%, to { width: calc(var(--n) * 1ch); }
}
@keyframes txt-code-typing-animation-caret {
  0%, 100% { border-right-color: var(--c); }
}
@keyframes txt-code-typing-animation-blink {
  0% { border-right-color: var(--c); }
  50% { border-right-color: transparent; }
}
@keyframes txt-code-typing-animation-row {
  0% { transform: translateY(0); }
  60.6% { transform: translateY(100%); }
  100% { transform: translateY(200%); }
}

@media (prefers-reduced-motion: reduce) {
  .txt-code-typing-animation, .txt-code-typing-animation *, .txt-code-typing-animation::before, .txt-code-typing-animation::after, .txt-code-typing-animation *::before, .txt-code-typing-animation *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Customizing this snippet

  • Color: set --txt-color on the element or a parent. Currently previewing #3b82f6.
  • Font size: set --txt-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 40px.
  • Speed: change the duration on the transition or animation shorthand. Staggered delays are relative, so they keep their rhythm.
  • Reduced motion: the rule at the end of the CSS turns the motion off for people who asked their OS for less of it. Keep it.

Similar text animations