返回 AiToEarn
typography.md
1 # Typography
2
3 ## Classic Typography Principles
4
5 ### Vertical Rhythm
6
7 Your line-height should be the base unit for ALL vertical spacing. If body text has `line-height: 1.5` on `16px` type (= 24px), spacing values should be multiples of 24px. This creates subconscious harmony; text and space share a mathematical foundation.
8
9 ### Modular Scale & Hierarchy
10
11 The common mistake: too many font sizes that are too close together (14px, 15px, 16px, 18px...). This creates muddy hierarchy.
12
13 **Use fewer sizes with more contrast.** A 5-size system covers most needs:
14
15 | Role | Typical Ratio | Use Case |
16 |------|---------------|----------|
17 | xs | 0.75rem | Captions, legal |
18 | sm | 0.875rem | Secondary UI, metadata |
19 | base | 1rem | Body text |
20 | lg | 1.25-1.5rem | Subheadings, lead text |
21 | xl+ | 2-4rem | Headlines, hero text |
22
23 Popular ratios: 1.25 (major third), 1.333 (perfect fourth), 1.5 (perfect fifth). Pick one and commit.
24
25 ### Readability & Measure
26
27 Use `ch` units for character-based measure (`max-width: 65ch`). Line-height scales inversely with line length: narrow columns need tighter leading, wide columns need more.
28
29 **Non-obvious**: Light text on dark backgrounds needs compensation on three axes, not just one. Bump line-height by 0.05–0.1, add a touch of letter-spacing (0.01–0.02em), and optionally step the body weight up one notch (regular → medium). The perceived weight drops across all three; fix all three.
30
31 **Paragraph rhythm**: Pick either space between paragraphs OR first-line indentation. Never both. Digital usually wants space; editorial/long-form can justify indent-only.
32
33 ## Font Selection & Pairing
34
35 The tactical selection procedure and the reflex-reject list live in [reference/brand.md](brand.md) under **Font selection procedure** and **Reflex-reject list** (loaded for brand-register tasks). The rest of this section covers the adjacent knowledge: anti-reflex corrections, system font use, and pairing rules.
36
37 ### Anti-reflexes worth defending against
38
39 - A technical/utilitarian brief does NOT need a serif "for warmth." Most tech tools should look like tech tools.
40 - An editorial/premium brief does NOT need the same expressive serif everyone is using right now. Premium can be Swiss-modern, can be neo-grotesque, can be a literal monospace, can be a quiet humanist sans.
41 - A children's product does NOT need a rounded display font. Kids' books use real type.
42 - A "modern" brief does NOT need a geometric sans. The most modern thing you can do is not use the font everyone else is using.
43
44 **System fonts are underrated**: `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui` looks native, loads instantly, and is highly readable. Consider this for apps where performance > personality.
45
46 ### Pairing Principles
47
48 **The non-obvious truth**: You often don't need a second font. One well-chosen font family in multiple weights creates cleaner hierarchy than two competing typefaces. Only add a second font when you need genuine contrast (e.g., display headlines + body serif).
49
50 When pairing, contrast on multiple axes:
51 - Serif + Sans (structure contrast)
52 - Geometric + Humanist (personality contrast)
53 - Condensed display + Wide body (proportion contrast)
54
55 **Never pair fonts that are similar but not identical** (e.g., two geometric sans-serifs). They create visual tension without clear hierarchy.
56
57 ### Web Font Loading
58
59 The layout shift problem: fonts load late, text reflows, and users see content jump. Here's the fix:
60
61 ```css
62 /* 1. Use font-display: swap for visibility */
63 @font-face {
64 font-family: 'CustomFont';
65 src: url('font.woff2') format('woff2');
66 font-display: swap;
67 }
68
69 /* 2. Match fallback metrics to minimize shift */
70 @font-face {
71 font-family: 'CustomFont-Fallback';
72 src: local('Arial');
73 size-adjust: 105%; /* Scale to match x-height */
74 ascent-override: 90%; /* Match ascender height */
75 descent-override: 20%; /* Match descender depth */
76 line-gap-override: 10%; /* Match line spacing */
77 }
78
79 body {
80 font-family: 'CustomFont', 'CustomFont-Fallback', sans-serif;
81 }
82 ```
83
84 Tools like [Fontaine](https://github.com/unjs/fontaine) calculate these overrides automatically.
85
86 **`swap` vs `optional`**: `swap` shows fallback text immediately and FOUT-swaps when the web font arrives. `optional` uses the fallback if the web font misses a small load budget (~100ms) and avoids the shift entirely. Pick `optional` when zero layout shift matters more than seeing the branded font on slow networks.
87
88 **Preload the critical weight only**: typically the regular-weight body font used above the fold. Preloading every weight costs more bandwidth than it saves.
89
90 **Variable fonts for 3+ weights or styles**: a single variable font file is usually smaller than three static weight files, gives fractional weight control, and pairs well with `font-optical-sizing: auto`. For 1–2 weights, static is fine.
91
92 ## Modern Web Typography
93
94 ### Fluid Type
95
96 Fluid typography via `clamp(min, preferred, max)` scales text smoothly with the viewport. The middle value (e.g., `5vw + 1rem`) controls scaling rate (higher vw = faster scaling). Add a rem offset so it doesn't collapse to 0 on small screens.
97
98 **Use fluid type for**: Headings and display text on marketing/content pages where text dominates the layout and needs to breathe across viewport sizes.
99
100 **Use fixed `rem` scales for**: App UIs, dashboards, and data-dense interfaces. No major app design system (Material, Polaris, Primer, Carbon) uses fluid type in product UI; fixed scales with optional breakpoint adjustments give the spatial predictability that container-based layouts need. Body text should also be fixed even on marketing pages, since the size difference across viewports is too small to warrant it.
101
102 **Bound your clamp()**: keep `max-size ≤ ~2.5 × min-size`. Wider ratios break the browser's zoom and reflow behaviour and make large viewports feel like the page is shouting.
103
104 **Scale container width and font-size together** so effective character measure stays in the 45–75ch band at every viewport. A heading that widens faster than its container drifts out of the comfortable measure at the top end.
105
106 ### OpenType Features
107
108 Most developers don't know these exist. Use them for polish:
109
110 ```css
111 /* Tabular numbers for data alignment */
112 .data-table { font-variant-numeric: tabular-nums; }
113
114 /* Proper fractions */
115 .recipe-amount { font-variant-numeric: diagonal-fractions; }
116
117 /* Small caps for abbreviations */
118 abbr { font-variant-caps: all-small-caps; }
119
120 /* Disable ligatures in code */
121 code { font-variant-ligatures: none; }
122
123 /* Enable kerning (usually on by default, but be explicit) */
124 body { font-kerning: normal; }
125 ```
126
127 Check what features your font supports at [Wakamai Fondue](https://wakamaifondue.com/).
128
129 ### Rendering polish
130
131 ```css
132 /* Even out heading line lengths (browser picks better break points) */
133 h1, h2, h3 { text-wrap: balance; }
134
135 /* Reduce orphans and ragged endings in long prose */
136 article p { text-wrap: pretty; }
137
138 /* Variable fonts: pick the right optical-size master automatically */
139 body { font-optical-sizing: auto; }
140 ```
141
142 **ALL-CAPS tracking**: capitals sit too close at default spacing. Add 5–12% letter-spacing (`letter-spacing: 0.05em` to `0.12em`) to short all-caps labels, eyebrows, and small headings. Real small caps (via `font-variant-caps`) need the same treatment, slightly gentler.
143
144 ## Typography System Architecture
145
146 Name tokens semantically (`--text-body`, `--text-heading`), not by value (`--font-size-16`). Include font stacks, size scale, weights, line-heights, and letter-spacing in your token system.
147
148 ## Accessibility Considerations
149
150 Beyond contrast ratios (which are well-documented), consider:
151
152 - **Never disable zoom**: `user-scalable=no` breaks accessibility. If your layout breaks at 200% zoom, fix the layout.
153 - **Use rem/em for font sizes**: This respects user browser settings. Never `px` for body text.
154 - **Minimum 16px body text**: Smaller than this strains eyes and fails WCAG on mobile.
155 - **Adequate touch targets**: Text links need padding or line-height that creates 44px+ tap targets.
156
157 ---
158
159 **Avoid**: More than 2-3 font families per project. Skipping fallback font definitions. Ignoring font loading performance (FOUT/FOIT). Using decorative fonts for body text.
160
160 lines MARKDOWN