14 CSS Typewriter Effect Designs 08 / 14

CSS Typewriter Variable Font Weight Morph

Each character of a variable font headline morphs from ultra-light to black weight as it "types in", using staggered font-variation-settings animations — no width tricks required.

Pure CSS MIT licensed
Live Demo Open in tab
Open in playground

The code

<div class="tw-08">
  <div class="tw-08__stage">
    <p class="tw-08__pre">Variable font axis animation</p>
    <h1 class="tw-08__word" aria-label="EVOLVE">
      <span style="--i:0">E</span>
      <span style="--i:1">V</span>
      <span style="--i:2">O</span>
      <span style="--i:3">L</span>
      <span style="--i:4">V</span>
      <span style="--i:5">E</span>
    </h1>
    <p class="tw-08__post">font-variation-settings "wght" morph</p>
  </div>
</div>
@import url('https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap');

.tw-08, .tw-08 *, .tw-08 *::before, .tw-08 *::after { box-sizing: border-box; margin: 0; padding: 0; }
.tw-08 ::selection { background: #f59e0b; color: #1a0e00; }

.tw-08 {
  --amber: #f59e0b;
  --gold: #fcd34d;
  --bg: #0d0900;
  font-family: 'Inter', system-ui, sans-serif;
  background: radial-gradient(ellipse at 50% 40%, #1a1000 0%, var(--bg) 65%);
  min-height: 340px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 24px;
}

.tw-08__stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.tw-08__pre, .tw-08__post {
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #4a3500;
  animation: tw-08-fadein 0.5s 0.2s both;
}

.tw-08__word {
  display: flex;
  gap: 0.02em;
  font-size: clamp(3rem, 12vw, 7rem);
  line-height: 1;
}

.tw-08__word span {
  display: inline-block;
  opacity: 0;
  font-variation-settings: 'wght' 100;
  color: var(--amber);
  letter-spacing: 0.05em;
  text-shadow: 0 0 0px transparent;
  animation: tw-08-stamp 0.6s cubic-bezier(0.2, 0, 0, 1) calc(var(--i) * 0.12s + 0.5s) both;
}

@keyframes tw-08-stamp {
  0%   { opacity: 0; font-variation-settings: 'wght' 100; letter-spacing: 0.3em; text-shadow: 0 0 0 transparent; }
  60%  { opacity: 1; font-variation-settings: 'wght' 950; letter-spacing: -0.02em; text-shadow: 0 0 30px rgba(245,158,11,0.6); }
  100% { opacity: 1; font-variation-settings: 'wght' 700; letter-spacing: 0.02em; text-shadow: 0 0 8px rgba(245,158,11,0.2); }
}

@keyframes tw-08-fadein {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .tw-08__word span {
    opacity: 1;
    font-variation-settings: 'wght' 700;
    letter-spacing: 0.02em;
    animation: none;
  }
}

How this works

With a variable font loaded, each letter is wrapped in its own <span> and receives a staggered animation-delay. The keyframe animates font-variation-settings: "wght" 100 to "wght" 900 and simultaneously fades opacity from 0 to 1. The result looks like each character is being stamped into the page at increasing weight — from a ghostly hairline to a bold terminal state.

A secondary letter-spacing keyframe compresses from a wide tracked-out state to normal, so the word appears to "collapse" into place as it types. This works on any variable font that has a wght axis — Google Fonts provides many (Inter, Fraunces, Roboto Flex) that cover the full 100–900 range.

Customize

  • Add a width axis animation ("wdth" 50 → 100) on Roboto Flex for characters that physically expand as they type in.
  • Reverse the effect — start at wght: 900 and end at wght: 300 — for a "fading ink" typewriter that starts bold and settles into a lighter weight.
  • Stagger direction: apply animation-delay from right to left for a right-to-left language typewriter or a right-anchored countdown effect.

Watch out for

  • Variable font font-variation-settings is not animatable in Safari before 16.4 — provide a @supports not (font-variation-settings: "wght" 900) fallback that uses a plain opacity fade.
  • Each character needs to be in its own <span>; this is verbose in HTML but unavoidable without JS injection for the per-character timing.
  • Not all variable fonts include the full wght range (100–900) — check the font's axis range with a tool like Wakamai Fondue before coding the keyframe end values.

Browser support

ChromeSafariFirefoxEdge
66+ 16.4+ 62+ 66+

Animating font-variation-settings requires Safari 16.4+ for smooth transitions.

Search CodeFronts

Loading…