K · 11 / 26
K — Kinetictype
Letters that move to be read.
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.
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.
- Marlo Vance, saved
- Halcyon Drive
- MirelaLow Orbit
- Tomoe, savedSaltwater Kids
- Northern FoldGlasshouse
- Orla WeirKite SeasonJuno Park
- 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.
- 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.
- Motion you can stopThe live name breathes between weights. One button pauses it, and it holds still when your system asks for less motion.
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 GRADText field
Moves wdthSelect
Moves wdthSwitch, checkbox, radio
Moves wghtSlider
Moves wghtProgress
Moves wghtSegments and tabs
Moves wdth · wght31 acts, by name.
List rows
Moves wdthCard and loading
Moves wdthToast
Moves wdthModal
Moves wdthSteps
Moves wght · wdth- Done: Ticket
- 2Details
- 3Pay
- 4Done
Badges and avatars
Moves wdth- Marlo Vance
- Halcyon Drive
- Low Orbit
- +12more
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.
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;
}
}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.
- --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
- 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
- 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
- Snap180msGrade on hover and press
- Settle700msA line stretching to its row
- Stagger40ms a letterArrivals and the wave
- Breathe4s, loopedThe live name; it pauses
- LoopsA pause past 5s
- FlashesNever over 3 a second
- Body textNever moves
- Reduced motionEvery line at rest
- 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.
North by Northwest titles
Saul Bass · 1959Credits sliding along the lines of a grid that turns into a building.Se7en titles
Kyle Cooper · 1995Scratched, jittering type cut to the beat, so the letters carry the dread.Stranger Things titles
Imaginary Forces · 2016Red outlined letters drifting in close, then locking into the logo.