Typography tokens provide a consistent, modular system for all text across the products. They are designed for clarity, readability, and hierarchy, while remaining flexible across devices.
The system uses four font families — a primary sans-serif for body and UI, a secondary display font for headings, a tertiary brand font for display and buttons, and a monospace for code. Fonts are self-hosted (Zalando Sans, Bugrino, IBM Plex Mono) or loaded via Adobe Typekit (trust-3a). For the full list of typography token values, see the Tokens page.
Font Sizes
The full type scale used across the system. Reference these tokens when setting font sizes on any element.
The scale uses a progressive step approach: +2px in the body range, +4px in the heading range, and +8px in the display range. This gives more granularity where it matters most.
| Token | Value | px Equivalent | Step |
|---|---|---|---|
| 0.625rem | 10px | — | |
| 0.75rem | 12px | +2px | |
| 0.875rem | 14px | +2px | |
| 1rem | 16px | +2px | |
| 1.125rem | 18px | +2px | |
| 1.25rem | 20px | +2px | |
| 1.375rem | 22px | +2px | |
| 1.5rem | 24px | +2px | |
| 1.75rem | 28px | +4px | |
| 2rem | 32px | +4px | |
| 2.25rem | 36px | +4px | |
| 2.5rem | 40px | +4px | |
| 3rem | 48px | +8px | |
| 3.5rem | 56px | +8px | |
| 4rem | 64px | +8px | |
| 4.5rem | 72px | +8px |
Headings
All headings use (trust-3a). Every level (h1–h6) uses fluid clamp() sizing that scales smoothly with viewport width — no breakpoints needed. Element defaults follow a traditional editorial scale (Major Third / ~1.25× progression).
Display contexts (hero pages, feature CTAs) use the separate --headline-size and --title-size role tokens applied via classes like , , and . Element defaults stay smaller; classes opt into display sizing.
Heading 1
Build systems that scale with your ambition
Heading 2
Every detail contributes to the whole
Heading 3
Structure creates clarity in complexity
Heading 4
Good defaults eliminate guesswork
Heading 5
Constraints unlock creative freedom
Heading 6
Small decisions compound over time
<h1>Build systems that scale with your ambition</h1>
<h2>Every detail contributes to the whole</h2>
<h3>Structure creates clarity in complexity</h3>
| Element | Range | Line Height | Letter Spacing |
|---|---|---|---|
h1 |
36px → 48px (fluid) | (1) | -0.02em |
h2 |
32px → 40px (fluid) | (1.2) | -0.01em |
h3 |
28px → 36px (fluid) | (1.2) | — |
h4 |
24px → 32px (fluid) | (1.2) | — |
h5 |
22px → 28px (fluid) | (1.2) | — |
h6 |
20px → 24px (fluid) | (1.4) | — |
Each heading uses clamp(min, fluid, max) with primitive --font-* tokens at the floor and ceiling — no new tokens, no media queries. Display variants use --headline-size (28px → 64px) and --title-size (24px → 48px) on classes like and , kept distinct from element defaults so plain <h1> and <h2> in body copy read at editorial size.
Body Text
The default paragraph style used for all running content. The token controls the base size globally — changing it updates paragraphs, inputs, code, tables, and buttons at once. Size modifier classes let you step up or down from the default.
Fluid sizing. Four of the five .text-size-* utilities are fluid — they grow with viewport width via clamp(rem + vw, ...). stays fixed at 14px (the accessibility floor). resolves to itself, so it's the cleanest way to reset a paragraph to body sizing inside a container that overrides font-size.
Reusable tokens. Each utility consumes a matching --text-size-* token (--text-size-xl, --text-size-l, --text-size-m, --text-size-s, --text-size-xs). Use the token directly on any custom selector when you want the utility's fluid sizing without applying the class.
Extra Large
Lead paragraphs and hero text that needs to stand out from regular body copy.
Large
Introductory text and section summaries that sit between headings and body text in the hierarchy.
Medium (default)
The default body text size. This is what you get without adding any size class — the baseline for all running content.
Small
Secondary content, supporting details, and supplementary information that doesn't need to compete with body text for attention.
Extra Small
Captions, footnotes, metadata, and fine print — available but not prominent.
<p class="text-size-xl">Lead paragraph text.</p>
<p class="text-size-l">Introductory text.</p>
<p>Default body text (no class needed).</p>
<p class="text-size-s">Smaller supporting text.</p>
<p class="text-size-xs">Captions and metadata.</p>
| Element | Font Size | Range (fluid) | Line Height |
|---|---|---|---|
→ clamp(var(--font-3xl), 1rem + 0.8vw, var(--font-5xl)) |
28 → 36px | (1.2) | |
→ clamp(var(--font-l), 1rem + 0.4vw, var(--font-2xl)) |
20 → 24px | (1.4) | |
| → | 16 → 18px | (1.4) | |
p (default) |
16 → 18px | (1.4) | |
→ clamp(var(--font-xs), 0.8rem + 0.15vw, var(--font-s)) |
14 → 16px | (1.6) | |
| → | 14px (fixed) | (1.6) |
Step rhythm at 1440px (typical desktop): xs 14 → s 15 → m 17.4 → l 21.8 → xl 28. Jumps stay in the 25–30% range (comfortable for prose hierarchy; research consensus avoids jumps above 50%).
Eyebrow
A small, uppercase label used to provide context above headings, within sections, or inline with other content. The class works on any element — <p>, <span>, <h2>, or anything else.
Case Study
Building a design system from the ground up
A design system is more than a collection of components — it is a shared language between design and engineering.
New components added to the library
Section Label
An eyebrow on an h2 resets it to the small uppercase style, useful when you need heading semantics without heading size.
<!-- On a paragraph -->
<p class="eyebrow">Case Study</p>
<h2>Building a design system from the ground up</h2>
<!-- On a span (inline) -->
<span class="eyebrow">Latest Update</span>
<!-- On a heading (semantic heading, eyebrow style) -->
<h2 class="eyebrow">Section Label</h2>
| Element | Token | Line Height | Value |
|---|---|---|---|
| 1.2 |
Blockquote
Used for pullquotes and highlighted passages. Renders in the secondary serif font with a left border accent.
Short quote
Good typography is invisible. Bad typography is everywhere.
Long quote
A design system is more than a collection of components — it is a shared language between design and engineering. When done well, it reduces inconsistency, speeds up delivery, and creates a foundation that scales with the product.
<blockquote>
<p>Good typography is invisible. Bad typography is everywhere.</p>
</blockquote>
| Element | Token | Line Height | Value |
|---|---|---|---|
blockquote |
1.4 |
Links
Links use text-color underlines with a hover transition. The default state shows text with a coloured underline. On hover, the text colour shifts to and the underline moves down slightly. External links (target="_blank") automatically show a share icon via ::after that inherits the link colour.
Inline link
Read the full brand guidelines before starting any new project.
External link
Typography is powered by Adobe Typekit and self-hosted variable fonts.
<!-- Inline link -->
<p>Read the full <a href="/brand">brand guidelines</a> before starting.</p>
<!-- External link (icon added automatically) -->
<p>Typography is powered by <a href="https://fonts.adobe.com/typekit" target="_blank" rel="noopener noreferrer">Adobe Typekit</a> and self-hosted variable fonts.</p>
| Property | Value |
|---|---|
| Default colour | |
| Underline colour | |
| Hover colour | |
| Underline offset | 2.5px → 4px on hover |
| Underline thickness | 1.5px |
| Transition | 0.3s all |
| External icon | ::after on a[target="_blank"], inherits currentColor |
Font Families
The system uses four font stacks, each with a distinct role.
Primary — Zalando Sans
Typography is the voice of design
Secondary — trust-3a
Typography is the voice of design
Tertiary — Bugrino
Typography is the voice of design
Quaternary — IBM Plex Mono
Typography is the voice of design
body { font-family: var(--font-primary); }
h1, h2, h3, h4, h5, h6 { font-family: var(--font-secondary); }
code, pre, kbd { font-family: var(--font-quaternary); }
| Token | Font | Source | Used For |
|---|---|---|---|
| Zalando Sans | Self-hosted (variable font) | Body text, UI, labels | |
| trust-3a | Adobe Typekit | Headings, blockquotes | |
| Bugrino | Self-hosted (woff2) | Brand display, eyebrows, buttons, badges | |
| IBM Plex Mono | Self-hosted (ttf) | Code, pre, kbd |
Font Weight
Available weight values from light to black. All headings default to regular weight.
Light
Regular
Medium
Semi-Bold
Bold
Extra-Bold
Black
font-weight: var(--font-weight-bold);
| Token | Value |
|---|---|
| 300 | |
| 400 | |
| 500 | |
| 600 | |
| 700 | |
| 800 | |
| 900 |
Font Width
The width of letters along the variable font's wdth axis (applied via CSS font-stretch). Zalando Sans supports 75% to 125%, exposed here as a five-step scale from condensed to expanded. Use narrower widths for compact UI chrome; wider widths for display moments that should feel broader on the page.
Condensed — 75%
Narrow — 87.5%
Normal — 100%
Wide — 112.5%
Expanded — 125%
<h2 data-font-width="expanded">Expanded headline</h2>
| Token | Value | Attribute |
|---|---|---|
| 75% | data-font-width="condensed" |
|
| 87.5% | data-font-width="narrow" |
|
| 100% | data-font-width="normal" |
|
| 112.5% | data-font-width="wide" |
|
| 125% | data-font-width="expanded" |
Line Height
Vertical rhythm values from tight display text to loose body copy. Headings use tighter values; body text uses looser values for readability.
Extra Small
Design tokens capture color, typography, spacing, and border values as reusable variables so that design and code stay in sync across every surface.
Small
Design tokens capture color, typography, spacing, and border values as reusable variables so that design and code stay in sync across every surface.
Medium
Design tokens capture color, typography, spacing, and border values as reusable variables so that design and code stay in sync across every surface.
Large
Design tokens capture color, typography, spacing, and border values as reusable variables so that design and code stay in sync across every surface.
Extra Large
Design tokens capture color, typography, spacing, and border values as reusable variables so that design and code stay in sync across every surface.
2X Large
Design tokens capture color, typography, spacing, and border values as reusable variables so that design and code stay in sync across every surface.
line-height: var(--line-height-l);
| Token | Value | Used For |
|---|---|---|
| 0.7 | Tight display text | |
| 1 | Tight display text | |
| 1.2 | Headings, eyebrows | |
| 1.4 | Body text, paragraphs | |
| 1.6 | Small text, captions | |
| 1.8 | Spacious body text |
Line Length
Horizontal rhythm — the measure of a line of text. Bringhurst's Elements of Typographic Style gives a satisfactory range of 45 to 75 characters per line for body text, with 66 characters widely regarded as ideal. Below 45 = display territory; above 75 = unsuitable for long-form reading.
Apply with data-line-length="<value>" on any text element. Values are named typographically — pick the role that fits the content, not a t-shirt size.
Headline (20ch)
Display titles where the line break becomes part of the design.
Small (40ch)
Narrow body — lead paragraphs, intro and CTA descriptions, punchy short copy that needs a tighter measure.
Body (55ch)
Standard body — short prose blocks, scroll-stack items, founder cards. The default workhorse measure for most body copy on the page.
Medium (65ch)
Long-form body — origin stories, error page lede, multi-paragraph editorial. Sits at Bringhurst's ideal-measure mark for sustained reading.
Wide (75ch)
Maximum comfortable measure for very long-form prose. The ceiling — beyond this, line-find fatigue sets in.
<p data-line-length="body">Standard body copy.</p>
<h1 data-line-length="headline">Display title.</h1>
| Token | Value | Used For |
|---|---|---|
| 20ch | Display titles, big numerals | |
| 40ch | Narrow body — leads, intros, CTA descriptions | |
| 55ch | Standard body — short prose, cards, beliefs | |
| 65ch | Long-form body — origin, articles | |
| 75ch | Maximum measure for very long-form prose |
Letter Spacing
Tracking values used for labels, eyebrows, and display text. Values are em-based so they scale proportionally with font size.
Small
Medium
Large
Extra Large
letter-spacing: var(--letter-spacing-xl);
| Token | Value | Used For |
|---|---|---|
| -0.03em | Negative tracking | |
| 0.03em | Subtle tracking | |
| 0.06em | Medium tracking | |
| 0.12em | Wide tracking | |
| 0.24em | Eyebrows, labels |
Type Roles
Four semantic roles compose the primitive tokens into building blocks. Each role defines four dimensions: size, weight, leading (line-height), and tracking (letter-spacing).
| Role | Size | Weight | Leading | Tracking | Used For |
|---|---|---|---|---|---|
| Headline | clamp(--font-4xl, 1rem + 5vw, --font-8xl) |
500 | (1) | -0.02em | Page hero, h1 |
| Title | clamp(--font-2xl, 0.8rem + 2vw, --font-6xl) |
500 | (1.2) | -0.01em | Section heads, h2 |
| Label | (14px) | 500 | (1) | (0.06em) | Eyebrows, meta, captions |
| Body | (18px) | 400 | (1.6) | 0 | Running text |
/* Use role tokens directly */
.custom-headline {
font-size: var(--headline-size);
font-weight: var(--headline-weight);
line-height: var(--headline-leading);
letter-spacing: var(--headline-tracking);
}
Headline and title sizes use clamp() for fluid scaling — they grow with the viewport between a minimum and maximum, with no breakpoints needed.