docs(typography): absorb tactical additions from typecraft-guide-skill

Merged ten tactical items from ehmo/typecraft-guide-skill into the typography
reference at the upstream author's request: dark-mode weight/tracking/leading
compensation, font-display: optional vs swap, preload-critical-weight-only,
variable fonts for 3+ weights, clamp() max-to-min ratio bound, container/
font-size coupling to preserve measure, text-wrap: balance / pretty,
font-optical-sizing: auto, quantified ALL-CAPS tracking (5-12%), and the
paragraph-rhythm rule (space OR indent, never both).

Skipped: platform-specific tables (iOS/Android/print), confidence markers,
severity-graded report format, academic sources, and the punctuation
subsection (em-dash prescription conflicts with the project copy rule).

Attribution lives in NOTICE.md, not inside the skill content.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-04-23 16:56:29 -07:00
co-authored by Claude Opus 4.7
parent e0ab3a73b7
commit 5613891aa6
13 changed files with 344 additions and 12 deletions
@@ -26,7 +26,9 @@ Popular ratios: 1.25 (major third), 1.333 (perfect fourth), 1.5 (perfect fifth).
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.
**Non-obvious**: Increase line-height for light text on dark backgrounds. The perceived weight is lighter, so text needs more breathing room. Add 0.05-0.1 to your normal line-height.
**Non-obvious**: Light text on dark backgrounds needs compensation on three axes, not just one. Bump line-height by 0.050.1, add a touch of letter-spacing (0.010.02em), and optionally step the body weight up one notch (regular → medium). The perceived weight drops across all three; fix all three.
**Paragraph rhythm**: Pick either space between paragraphs OR first-line indentation. Never both. Digital usually wants space; editorial/long-form can justify indent-only.
## Font Selection & Pairing
@@ -81,6 +83,12 @@ body {
Tools like [Fontaine](https://github.com/unjs/fontaine) calculate these overrides automatically.
**`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.
**Preload the critical weight only**: typically the regular-weight body font used above the fold. Preloading every weight costs more bandwidth than it saves.
**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 12 weights, static is fine.
## Modern Web Typography
### Fluid Type
@@ -91,6 +99,10 @@ Fluid typography via `clamp(min, preferred, max)` scales text smoothly with the
**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.
**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.
**Scale container width and font-size together** so effective character measure stays in the 4575ch band at every viewport. A heading that widens faster than its container drifts out of the comfortable measure at the top end.
### OpenType Features
Most developers don't know these exist. Use them for polish:
@@ -114,6 +126,21 @@ body { font-kerning: normal; }
Check what features your font supports at [Wakamai Fondue](https://wakamaifondue.com/).
### Rendering polish
```css
/* Even out heading line lengths (browser picks better break points) */
h1, h2, h3 { text-wrap: balance; }
/* Reduce orphans and ragged endings in long prose */
article p { text-wrap: pretty; }
/* Variable fonts: pick the right optical-size master automatically */
body { font-optical-sizing: auto; }
```
**ALL-CAPS tracking**: capitals sit too close at default spacing. Add 512% 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.
## Typography System Architecture
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.