Typography
Professional typography for user interfaces, grounded in principles from the masters.
"Typography exists to honor content." — Robert Bringhurst
Reference Files
For detailed guidance on specific topics, consult these references:
| Topic | When to Read |
|---|---|
| masters.md | Seeking authoritative backing, making nuanced judgments, understanding "why" |
| variable-fonts.md | Using variable fonts, fluid weight, performance optimization |
| font-loading.md | FOIT/FOUT issues, preloading, Core Web Vitals, self-hosting |
| opentype-features.md | Ligatures, tabular numbers, stylistic sets, slashed zero |
| fluid-typography.md | clamp(), text-wrap, truncation, vertical rhythm, font smoothing |
| tailwind-integration.md | Tailwind typography utilities, prose plugin, customization |
| internationalization.md | RTL languages, Arabic/Hebrew, CJK, bidirectional text |
Output Formats
Type System Recommendations
## Type System ### Scale - Base: [size, e.g., 16px] - Ratio: [e.g., Minor Third 1.200] - Rationale: [why this ratio] ### Hierarchy | Level | Size | Weight | Line Height | Letter Spacing | Use | |-------|------|--------|-------------|----------------|-----| | Display | ... | ... | ... | ... | Hero, marketing | | H1 | ... | ... | ... | ... | Page titles | | H2 | ... | ... | ... | ... | Section heads | | Body | ... | ... | ... | ... | Paragraphs | | Small | ... | ... | ... | ... | Captions, labels | ### Fonts - Primary: [font] — [rationale] - Secondary: [font, if applicable] - Mono: [font, if applicable] ### Implementation [Ready-to-use CSS/Tailwind]
Typography Audits
## Typography Audit ### Issues | Element | Problem | Recommendation | |---------|---------|----------------| | ... | ... | ... | ### Quick Wins - [Immediate improvement 1] - [Immediate improvement 2]
Core Principles
The Four Fundamentals (Bringhurst)
The most important typographic considerations for body text:
- •Point size — 16px minimum for body; 14px absolute floor for secondary text
- •Line spacing — 1.5-1.7 for body; 1.1-1.3 for headings
- •Line length — 45-75 characters (66 ideal); use
max-w-prose(~65ch) - •Font choice — Match typeface to content and context
Hierarchy Through Contrast
Establish hierarchy using multiple dimensions:
| Dimension | Low Contrast | High Contrast |
|---|---|---|
| Size | 14px → 16px | 16px → 48px |
| Weight | 400 → 500 | 400 → 700 |
| Color | Gray-600 → Gray-900 | Gray-400 → Black |
| Case | Normal | UPPERCASE |
"Use one typeface per design. Avoid italics and bold—rely on gradations of scale instead." — Massimo Vignelli
Restraint
- •1-2 font families maximum — One serif, one sans if pairing
- •3-4 heading levels in practice — Deeper nesting usually signals structure problems
- •Stick to your type scale — Resist arbitrary sizes
- •Let whitespace work — Don't fill every gap
"In the new computer age, the proliferation of typefaces represents a new level of visual pollution." — Massimo Vignelli
Type Scales
Modular Scale Ratios
| Name | Ratio | Character |
|---|---|---|
| Minor Second | 1.067 | Subtle, conservative |
| Major Second | 1.125 | Gentle, professional |
| Minor Third | 1.200 | Balanced, versatile |
| Major Third | 1.250 | Bold, impactful |
| Perfect Fourth | 1.333 | Strong hierarchy |
| Golden Ratio | 1.618 | Dramatic, editorial |
Practical Scale (Minor Third @ 16px)
--text-xs: 12px; /* 0.75rem */ --text-sm: 14px; /* 0.875rem */ --text-base: 16px; /* 1rem */ --text-lg: 18px; /* 1.125rem — not in pure scale */ --text-xl: 20px; /* 1.25rem */ --text-2xl: 24px; /* 1.5rem */ --text-3xl: 30px; /* 1.875rem */ --text-4xl: 36px; /* 2.25rem */ --text-5xl: 48px; /* 3rem */
When to Deviate
- •Marketing/hero: Larger jumps allowed
- •Dense data interfaces: Tighter scale
- •Mobile: Slightly larger base (17-18px)
Spacing Guidelines
Line Height by Context
| Context | Line Height | Rationale |
|---|---|---|
| Body text | 1.5-1.7 | Generous for readability |
| Headings | 1.1-1.3 | Tighter, especially large sizes |
| UI labels | 1.2-1.4 | Compact but legible |
| Buttons | 1.0-1.25 | Single line, tight |
"The eye does not read letters, but the space between them." — Adrian Frutiger
Letter Spacing
| Context | Tracking | CSS |
|---|---|---|
| Body text | Default or +0.01em | tracking-normal |
| All caps | +0.05em to +0.1em | tracking-wide / tracking-wider |
| Large headings | -0.01em to -0.02em | tracking-tight |
| Small text (<14px) | +0.01em to +0.02em | tracking-wide |
All-caps rule: Always add tracking. Keep short (1-3 words).
Paragraph Spacing
- •Between paragraphs: 1em to 1.5em (equal to or slightly more than line-height)
- •After headings: Reduced top margin on first paragraph
- •Between sections: 2-3× paragraph spacing
Font Selection
System Font Stacks
/* Sans-serif (modern) */ font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; /* Serif */ font-family: ui-serif, Georgia, Cambria, "Times New Roman", serif; /* Monospace */ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
Safe Web Font Recommendations
| Category | Fonts | Use Case |
|---|---|---|
| Sans-serif | Inter, Source Sans 3, Work Sans, DM Sans | UI, body text |
| Serif | Source Serif 4, Lora, Merriweather, Literata | Editorial, long-form |
| Monospace | JetBrains Mono, Fira Code, Source Code Pro | Code, data |
| Display | Fraunces, Epilogue, Outfit | Headlines |
Pairing Principles
- •Pair by contrast — Serif + sans-serif
- •Match x-height — For visual harmony when mixed
- •Ensure weight availability — Both need needed weights/styles
"A father should not have a favorite among his daughters." — Hermann Zapf (on his typefaces)
Modern CSS Typography
Text Wrapping
/* Balanced line lengths for headings (≤6 lines) */
h1, h2, h3, blockquote, figcaption {
text-wrap: balance;
}
/* Prevent orphans in body text */
p, li {
text-wrap: pretty;
}
Caveat: Don't use balance inside bordered containers—creates visual imbalance.
Fluid Typography
/* Font scales smoothly between breakpoints */
h1 {
font-size: clamp(2rem, 1rem + 4vw, 4rem);
line-height: clamp(1.1, 1.3 - 0.1vw, 1.3);
}
body {
font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
}
See fluid-typography.md for complete scale.
Text Truncation
/* Single line */
.truncate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Multi-line (2 lines) */
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
Dark Mode Typography
Weight Adjustment
Text appears heavier on dark backgrounds. Reduce weight slightly:
@media (prefers-color-scheme: dark) {
body {
font-weight: 350; /* Instead of 400 */
}
h1, h2, h3 {
font-weight: 600; /* Instead of 700 */
}
}
Font Smoothing
Apply antialiasing on dark backgrounds to counter perceived boldness:
.dark-bg {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
Color Contrast
- •Avoid pure white (#fff) on pure black (#000)—too harsh
- •Use off-white (#f5f5f5) and near-black (#1a1a1a)
- •Aim for 10:1 to 15:1 contrast in dark mode
Typographic Details
Quotation Marks
Use curly quotes, not straight:
- •Correct: "Hello" and 'world'
- •Incorrect: "Hello" and 'world'
Dashes
| Type | Character | Use |
|---|---|---|
| Hyphen | - | Word breaks, compounds |
| En dash | – | Ranges (2020–2024), relationships |
| Em dash | — | Parenthetical statements |
Numbers
| Type | Use Case | CSS |
|---|---|---|
| Tabular | Tables, prices, alignment | font-variant-numeric: tabular-nums |
| Proportional | Body text | font-variant-numeric: proportional-nums |
| Old-style | Editorial content | font-variant-numeric: oldstyle-nums |
| Slashed zero | Code, data | font-feature-settings: "zero" 1 |
See opentype-features.md for complete reference.
Accessibility
Minimums
| Element | Minimum | Preferred |
|---|---|---|
| Body text | 16px | 16-18px |
| Secondary text | 14px | 14-16px |
| Legal/caption | 12px | 12px + increased tracking |
| Contrast ratio | 4.5:1 | 7:1 |
User Preferences
/* Use relative units so users can scale */
body {
font-size: 1rem; /* Not 16px */
}
/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
* {
transition: none !important;
}
}
Dyslexia Considerations
- •Avoid justified text
- •Prefer sans-serif with distinct letterforms (a vs α, l vs 1 vs I)
- •Generous line height and paragraph spacing
- •Consider offering OpenDyslexic as option
Common Mistakes
Avoid
- •All-caps body text or long headings
- •Centered body paragraphs
- •Line length over 80 characters
- •Insufficient contrast for "aesthetic" reasons
- •Mixing too many font families (>2)
- •Decorative fonts for UI text
- •Justified text on the web
- •Tiny gray text on white backgrounds
- •Letter-spacing on Arabic text
Watch For
- •Orphans and widows in prominent text
- •Inconsistent heading hierarchy
- •Missing font fallbacks
- •Layout shift from web font loading
- •Underlined text that isn't a link
Quick Implementation
Minimal Professional Setup
:root {
--font-sans: Inter, ui-sans-serif, system-ui, sans-serif;
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
}
body {
font-family: var(--font-sans);
font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
line-height: 1.6;
font-feature-settings: "kern" 1, "liga" 1, "calt" 1;
}
h1, h2, h3 {
line-height: 1.2;
text-wrap: balance;
letter-spacing: -0.02em;
}
p {
text-wrap: pretty;
max-width: 65ch;
}
code {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums slashed-zero;
}
@media (prefers-color-scheme: dark) {
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
Tailwind Quick Start
<article class=" prose prose-gray lg:prose-lg prose-headings:text-balance prose-p:text-pretty dark:prose-invert max-w-prose mx-auto "> <!-- Content --> </article>
See tailwind-integration.md for complete patterns.