K · 11 / 26

K — Kinetictype

Letters that move to be read.

The style

Type that changes shape to be read.

Kinetic type is lettering that moves, and moves on purpose: to arrive, to stress a word, to keep time. It grew up in film titles. In 1959 Saul Bass ran the credits of North by Northwest along the grid of a glass office front, and type stopped being a card held still between scenes. In 1995 Kyle Cooper’s scratched, jittering titles for Se7en made the letters themselves feel uneasy.

On screens, for years, a word could only slide, scale or fade as one block. In 2016 OpenType 1.8 added font variations: one file holding a continuous range of weights, widths and slants. Now a letter can change its own shape as smoothly as it moves. Roboto Flex, the face on this page, has thirteen axes.

The rule is older than any of it: motion ends on a still, readable word.

In use

The lineup, set to fit.

Afterglow, a festival app on a Saturday night at 21:48. The lineup stretches every name to fill its row, the timetable condenses them into three stages, and the act on stage now breathes in lime.

Afterglow26Lake Orrin · 14–16 August
  1. Marlo Vance, saved
  2. Halcyon Drive
  3. MirelaLow Orbit
  4. Tomoe, savedSaltwater Kids
  5. Northern FoldGlasshouse
  6. Orla WeirKite SeasonJuno Park

  1. Names fill their rowsEach line of the lineup is measured and set to the width that fills the row, anywhere from 25 to 151 on the width axis. Only a line the axis can’t fit changes size. Nothing is squashed.
  2. The grid condensesIn the timetable a name drops to a narrow width, so a 45-minute set still carries its whole name in a phone’s column.
  3. Motion you can stopThe live name breathes between weights. One button pauses it, and it holds still when your system asks for less motion.
One line, three widths
Halcyon Drivewdth 25 · leaves the row half empty
Halcyon Drive
wdth fitted · fills it, edge to edge
Halcyon Drivewdth 151 · runs over the edge
The kit

Every part, every state.

The parts that app is built from. Each changes state on one axis, named on its tile: grade for a press, width for an arrival, weight for a value. Rows of states hold still for comparison; everything else works.

Button

Moves GRAD
Hover raises the grade, not the weight: heavier, at the same width

Text field

Moves wdth

Select

Moves wdth
The list stays native; the choice arrives at width

Switch, checkbox, radio

Moves wght
Quiet type in the app
Tell me
Ticket
Chosen labels go to 820; the rest rest at 400

Slider

Moves wght
The number’s weight is the value

Progress

Moves wght
Offline map
0%
Each letter goes from 150 to 900 as the bar passes

Segments and tabs

Moves wdth · wght

31 acts, by name.

List rows

Moves wdth
Hover widens the name in place; the row stays put

Card and loading

Moves wdth
Lake · Sat 19:30NEWMirelaLisbon-born, Berlin-based. Cello, a drum machine and one long song per set.
Loaded · the name arrives at 151
Loading is the name at its thinnest and narrowest, held still

Toast

Moves wdth
Tomoe saved · 21:00
Arrives from wdth 25 in 0.7s; stays until dismissed

Modal

Moves wdth
The title lands at width once; the scrim never moves

Steps

Moves wght · wdth
  1. Done: Ticket
  2. 2Details
  3. 3Pay
  4. 4Done
Now is 950 at full width; done and next fall back narrow

Badges and avatars

Moves wdth
LIVENEWSOLD OUT3 saved sets
  • Marlo Vance
  • Halcyon Drive
  • Low Orbit
  • +12more
Initials fill the circle: two at 151, three at 50
Signature

Five axes and a word.

Type a word and scrub weight, width, optical size, slant and grade. Pick a motion: a wave, a breath, a glitch that never flashes. The CSS below is the preview’s own, keyframes and pause included.

Motion

Each letter rises and thickens, 80ms after the one before.

Kinetic

Your system asks for less motion, so the word holds still. The CSS keeps the motion behind that same setting.

/* Roboto Flex, from Google Fonts with every axis */
.kinetic {
  font-family: 'Roboto Flex', system-ui, sans-serif;
  font-variation-settings:
    'wght' 760,
    'wdth' 112,
    'opsz' 144,
    'slnt' 0,
    'GRAD' 0;
}

/* Wrap each letter in a span with --i: 0, 1, 2… */
.kinetic span {
  display: inline-block;
  font-variation-settings: inherit;
}
@media (prefers-reduced-motion: no-preference) {
  .kinetic span {
    animation: wave 1.6s ease-in-out infinite;
    animation-delay: calc(var(--i) * 80ms);
  }
  .paused .kinetic,
  .paused .kinetic span {
    animation: none;
  }
}
@keyframes wave {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-0.12em);
    font-variation-settings:
      'wght' 1000,
      'wdth' 142,
      'opsz' 144,
      'slnt' 0,
      'GRAD' 0;
  }
}

Tokens

The system, in numbers.

Seven colours with their contrast, the five axes and their ranges, four roles in the design space, the motion and its limits. Copy them as custom properties, with the grade-hover button and the breathe.

Colour
  • --night #0c0c0bThe page: every ground
  • --stage #171716Surfaces: cards, fields, the app
  • --rig #34342fRules and borders, never type
  • --paper #f3f3ecType, 17.7:1
  • --paper-2 #a8a89fQuiet type, 8.2:1
  • --lime #c6ff3dSpot: saved, selected, big type, 16.5:1
  • --coral #ff6b4fLive and errors, 6.9:1
Axes
  • wghtWeight100 to 1000, default 400Rank, and the breathe on the live name
  • wdthWidth25 to 151, default 100Fitting a line to its row
  • opszOptical size8 to 144, default 14Follows the size; tighter, finer at display
  • slntSlant-10 to 0, default 0A lean for things in motion, never body
  • GRADGrade-200 to 150, default 0Hover and press: heavier with no reflow
Type
  • AfterglowPoster · 54–160px · wght 900 · wdth fitted · opsz 144
  • Now on stageHeadline · 32–76px · wght 820 · wdth 112 · opsz auto
  • Gates open at four.Body · 16–18px · wght 400 · wdth 100 · opsz auto
  • The Lantern ChoirGrid · 12–14px · wght 700 · wdth 40 · opsz auto
Motion
  • Snap180msGrade on hover and press
  • Settle700msA line stretching to its row
  • Stagger40ms a letterArrivals and the wave
  • Breathe4s, loopedThe live name; it pauses
One ease: cubic-bezier(0.16, 1, 0.3, 1)
Limits
  • LoopsA pause past 5s
  • FlashesNever over 3 a second
  • Body textNever moves
  • Reduced motionEvery line at rest
Spacing
  • 4
  • 8
  • 12
  • 16
  • 24
  • 32
  • 48
  • 64
:root {
  /* Night stage */
  --night: #0c0c0b;
  --stage: #171716;
  --rig: #34342f;
  --paper: #f3f3ec;
  --paper-2: #a8a89f;
  --lime: #c6ff3d;
  --coral: #ff6b4f;

  /* One variable face: Roboto Flex */
  --font: 'Roboto Flex', system-ui, sans-serif;
  --wdth: 100; /* 25 to 151 */
  --slnt: 0; /* -10 to 0 */
  --grad: 0; /* -200 to 150 */

  /* Motion */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --snap: 180ms;
  --settle: 700ms;
  --stagger: 40ms;
  --breathe: 4s;
}

/* Weight rides font-weight; the other axes read the custom properties,
   so any element can move one axis without restating the rest. */
* {
  font-variation-settings:
    'wdth' var(--wdth),
    'slnt' var(--slnt),
    'GRAD' var(--grad);
}

/* Hover raises the grade, not the weight: no reflow, no shift. */
.button {
  transition: font-variation-settings var(--snap) var(--ease);
}
.button:hover {
  --grad: 150;
}
.button:active {
  --grad: -120;
}

/* A loop that breathes, only for those who want motion. */
@media (prefers-reduced-motion: no-preference) {
  .breathe {
    animation: breathe var(--breathe) ease-in-out infinite alternate;
  }
  .paused .breathe {
    animation-play-state: paused;
  }
}
@keyframes breathe {
  from {
    font-weight: 640;
    font-variation-settings: 'wdth' 96, 'slnt' 0, 'GRAD' 0;
  }
  to {
    font-weight: 920;
    font-variation-settings: 'wdth' 118, 'slnt' 0, 'GRAD' 0;
  }
}

Do

  • Move display type and leave body text still. A paragraph is for reading; it should not have to be caught.
  • Change shape on an axis before you move a block. A word that thickens or widens in place stays where the eye left it.
  • End every motion on a still, readable frame, and give any loop past five seconds a pause.
  • Use grade for hover and press. It adds weight without changing the width, so nothing beside it moves.

Don’t

  • Don’t move what people read

    Letters that drift inside a paragraph make the eye chase every word. Motion belongs to a headline, a name, a number.
  • Don’t flash

    Inverting or blinking type more than three times a second can trigger seizures. A glitch can jump in place without a flash.
  • Don’t let it never settle

    A word that loops forever with no rest and no pause never becomes readable. Give it an end, or give people a stop.

In the wild

Where the style shows up outside this page.

  1. North by Northwest titles

    Saul Bass · 1959Credits sliding along the lines of a grid that turns into a building.
  2. Se7en titles

    Kyle Cooper · 1995Scratched, jittering type cut to the beat, so the letters carry the dread.
  3. Stranger Things titles

    Imaginary Forces · 2016Red outlined letters drifting in close, then locking into the logo.