---
name: typography-systems
description: Build modular type scales, pair fonts with intent, and create hierarchy through size, weight, spacing, and color — not decoration.
---

# Typography Systems

Type scales, font pairing, and hierarchy that carries the design

Typography isn't holding your design — it IS your design. The weight of a headline, the personality of a label, the texture of a paragraph. If you're reaching for your usual font, you're not designing.

## The Modular Scale

Pick a ratio and stick to it. Every type size in your system should come from the same scale.

| Scale | Ratio | Best for |
|-------|-------|----------|
| Minor second | 1.067 | Subtle, dense UI |
| Major second | 1.125 | Clean SaaS, dashboards |
| Minor third | 1.2 | Editorial, content-rich |
| Major third | 1.25 | Bold, marketing pages |
| Perfect fourth | 1.333 | Dramatic, display-heavy |

Example — Major third (1.25) starting at 1rem:
```
0.64rem  (xs)    — captions, metadata
0.8rem   (sm)    — secondary text, labels
1rem     (base)  — body text
1.25rem  (lg)    — lead text, small headings
1.563rem (xl)    — h4, section headings
1.953rem (2xl)   — h3, page section titles
2.441rem (3xl)   — h2, page titles
3.052rem (4xl)   — h1, hero headlines
```

## The Hierarchy System

Every heading level should be distinguishable by at least TWO properties:

| Level | Size | Weight | Color | Spacing |
|-------|------|--------|-------|---------|
| h1 | 3xl+ | Bold/Black | Primary | Tight (-0.02em) |
| h2 | 2xl | Semibold | Primary | Tight (-0.01em) |
| h3 | xl | Semibold | Primary | Normal |
| h4 | lg | Medium | Secondary | Normal |
| h5 | base | Semibold | Secondary | Normal |
| h6 | sm | Medium | Tertiary | Wide (0.02em) |
| Body | base | Regular | Primary | Normal |
| Caption | sm | Regular | Secondary | Wide (0.01em) |
| Label | xs | Medium | Tertiary | Wide (0.04em) |

## Font Pairing

### The Contrast Axis
Pair fonts that differ on a clear axis:

| Combination | Feel | Example |
|-------------|------|---------|
| Serif display + sans body | Editorial, authoritative | Fraunces + Instrument Sans |
| Geometric sans display + humanist sans body | Modern, friendly | Outfit + Source Sans |
| Display sans + mono body/data | Technical, precise | Space Grotesk + JetBrains Mono |
| One family, multiple weights | Restrained, cohesive | Instrument Serif (italic for emphasis) |

### Never Pair
- Two geometric sans-serifs (Inter + Poppins = no contrast).
- Two humanist sans-serifs (Source Sans + Open Sans = indistinguishable).
- Two serifs (unless one is a slab and the other a Didone — extreme contrast).
- More than 3 families total (including mono).

### Font Selection Rules

1. **Body text**: prioritize readability at 16px+ body size. Test at 14px for dense UI.
2. **Display text**: prioritize personality. This is where brand voice lives.
3. **Data/mono**: must have tabular figures (numbers align vertically in tables).
4. **Avoid overused defaults**: Inter, Roboto, Arial, system-ui for display. These are fine for body in dense UI but never for headlines.
5. **Variable fonts**: prefer when available — fewer HTTP requests, smoother weight transitions.

## Line Height & Measure

| Context | Line height | Measure (max-width) |
|---------|-------------|---------------------|
| Body text | 1.5–1.6 | 45–75ch |
| Headings (single line) | 1.1–1.2 | N/A |
| Headings (multi-line) | 1.2–1.3 | Constrained |
| Captions/labels | 1.3–1.4 | N/A |
| Data/tables | 1.4–1.6 | N/A |
| Block quotes | 1.5–1.7 | 35–55ch |

## Responsive Typography

### Fluid Type with clamp()

```css
h1 {
  font-size: clamp(2rem, 1.5rem + 2.5vw, 3.5rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
}

body {
  font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
  line-height: 1.5;
}
```

The formula: `clamp(min, preferred, max)` where preferred = `A + Bvw`.
Calculate A and Y-intercept: `A = min_size - (max_size - min_size) * (min_viewport / (max_viewport - min_viewport))`.

### Breakpoint Adjustments

Even with fluid type, set breakpoint-specific overrides for:
- **Navigation**: font sizes that work at 375px may need adjustment at 1440px.
- **Multi-column layouts**: body text in a narrow column can be smaller than full-width body.
- **Hero headlines**: test the longest heading copy at every breakpoint. If it overflows, reduce the clamp max or rewrite the copy.

## Letter Spacing as Register

| Context | Letter spacing |
|---------|---------------|
| Large display text (> 2rem) | -0.02em to -0.03em (tighter feels more refined) |
| Headings | -0.01em to 0 |
| Body text | 0 (default) |
| Small text (< 0.875rem) | 0.01em (slightly wider aids readability) |
| Labels/captions (uppercase) | 0.04em to 0.08em (uppercase needs breathing room) |
| Buttons | 0.02em to 0.04em |

## Typography Anti-Patterns

- **Single weight for everything**: all regular, or all bold. No hierarchy.
- **Font size without line-height**: `font-size: 2rem` without `line-height: 1.1` is a disaster.
- **Centered multi-line text**: ragged-right is more readable for paragraphs longer than 2 lines.
- **Justified text without hyphenation**: creates rivers of white space. Add `hyphens: auto` if you must justify.
- **Text that overflows its container**: long heading words + large clamp scales + narrow grids cause headline overflow on tablet/mobile. Test the heading copy at every breakpoint.
- **Placeholder text as the only label**: disappears on focus, no persistent reference.
- **Low-contrast body text**: `color: gray` on near-white is the #1 readability failure.
- **Mixing font sizes that are too close**: 14px and 16px in the same context looks like a mistake, not a hierarchy. Use the scale — skip sizes if needed.

## PageWeave-Specific

On PageWeave, fonts are loaded via `html_head` (Google Fonts proxied for privacy):

```html
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,300..700&family=Instrument+Sans:wght@400..700&display=swap" rel="stylesheet">
```

Assign in theme CSS or page-level `additional_html_head_html`:

```css
h1, h2, h3 { font-family: "Fraunces", serif; }
body { font-family: "Instrument Sans", sans-serif; }
```

Variable fonts with axis ranges (like Fraunces `opsz,wght`) give you optical sizing — the lettershapes adjust for each size, improving readability at small sizes and elegance at large sizes.