Working type director's reference for selecting, pairing, and shipping typefaces with real taste. Covers a broad, opinionated catalog of typefaces and foundries (libre through commercial), a mood/era/register-driven selection framework that never collapses to one answer, font pairing as logic, fluid type scales, variable-font axes (incl. opsz/GRAD), OpenType features, web-font performance (subsetting, font-display, size-adjust fallback metrics), and licensing literacy (SIL OFL vs commercial EULA, desktop/web/app, trials). Explicitly retires the overused AI-design defaults (Inter, Roboto, Montserrat, Poppins, Fraunces, Geist, Söhne, the Fontshare/ITF starter pack) and names fresher alternatives in every role. Use for font selection, pairing, type scales, web-font optimization, variable fonts, OpenType, and typographic systems. NOT for logo/wordmark design, icon fonts, general CSS, or image-based/raster typography.
8k tokens
context cost
the whole folder, loaded on every use
2
files
instructions only
0
copies elsewhere
how many repositories repackaged it
177
stars on the repo
on the repository, not the skill itself
Install
one command, takes just this skill from the repository
Written by someone who picks type for a living. The goal of this skill is breadth and taste, not a blessed shortlist. There is never one right typeface — there is a right *register*, and several good faces that hit it at different budgets. If you reach for the same four fonts every time, you are not choosing; you are defaulting. Stop defaulting.
When to Use This Skill
✅ Use for:
Font selection and pairing driven by mood / era / industry / register, not by habit
Typographic hierarchy and tokens for design systems
Type scales (modular ratios, fluid clamp())
Variable-font integration and axis control (wght, wdth, opsz, slnt, GRAD)
Web-font performance (subsetting, font-display, self-host vs CDN, size-adjust fallback metrics to kill CLS)
OpenType feature implementation (ligatures, small caps, numerals, stylistic sets)
Licensing decisions (OFL vs commercial EULA; desktop/web/app; trial fonts)
Accessibility for type (WCAG contrast, minimum sizes, zoom, line/letter spacing)
Dark-mode typographic compensation
Multilingual support (RTL, CJK, diacritics, character-set coverage)
❌ Do NOT use for:
Logo or wordmark creation → design-system-creator
Icon fonts / icon systems → web-design-expert (use SVG, not icon fonts)
General CSS unrelated to type
Image-based or rasterized lettering → different domain
Brand naming or strategy → this is visual implementation
Kinetic/motion typography → native-app-designer
0. Retire the Defaults (read this first)
These faces are not *bad*. They are *exhausted* — reached for reflexively, so they signal "a machine or a hurried human picked this," not "someone chose this." If a brief has no reason to use one of these, don't. For each: one sentence on why it's a cliché, then two fresher faces that fill the same role.
| Overused face | Why it reads as a cliché | Reach for instead |
|---|---|---|
| Inter (Rasmus Andersson, OFL) | The default UI sans of the entire 2018–2025 web; competent and invisible to the point of anonymity. | Hanken Grotesk (Alfredo Marco Pradil, OFL — warmer humanist UI sans) · Public Sans (USWDS, OFL — neutral but distinct) · paid: Söhne is *also* now overused; try Untitled Sans (Klim) instead. |
| Roboto (Christian Robertson, Apache) | Android's system font; "I used whatever was already loaded." | Schibsted Grotesk (Bakken & Bæck, OFL) · Onest (OFL) |
| Open Sans (Steve Matteson, Apache) | The 2013 "safe corporate" sans; reads as a CMS template. | Source Sans 3 (Paul Hunt / Adobe, OFL) · IBM Plex Sans (Bold Monday for IBM, OFL) |
| Montserrat (Julieta Ulanovsky, OFL) | Geometric "startup deck" sans, over-set at heavy weights everywhere. | Hanken Grotesk · paid: Aktiv Grotesk (Dalton Maag) or GT America (Grilli Type) |
| Poppins (Indian Type Foundry, OFL) | The "friendly app" geometric circle-o sans of a thousand landing pages. | Gabarito (OFL, geometric with character) · Figtree (OFL) · paid: Visby (Connary Fagen) |
| Lato (Łukasz Dziedzic, OFL) | 2010s humanist default; pleasant, forgettable. | Instrument Sans (Rodrigo Fuenzalida + Jordan Egstad, OFL) · Mona Sans (GitHub, OFL) |
| Helvetica / Helvetica Neue (Linotype) | "Neutral" became a cliché the moment everyone agreed it was neutral; also a paid license many fake with Arial. | Neue Haas Grotesk (the real thing, Linotype/Monotype) if you must; or pivot to a grotesque with grit: GT America (Grilli Type), ABC Diatype (Dinamo). Libre swap: Archivo (Omnibus-Type, OFL). |
| Fraunces (Undercase Type, OFL) | The "soft serif with the wonky g and opsz axis" that became *the* indie-SaaS display serif. | Newsreader (Production Type, OFL — has opsz too, far less seen) · paid: Signifier (Klim) or Domaine (Klim) for high-contrast display. |
| Geist (Vercel, OFL) | Ships with every Next.js starter; "I scaffolded this an hour ago." | Sans: Mona Sans / Hubot Sans (GitHub, OFL) or Hanken Grotesk. Mono: Commit Mono (OFL) or Martian Mono (OFL). |
| Söhne (Klim) | The premium-newsletter / AI-company house sans of 2021–present (you've seen it on a dozen "we raised a Series A" pages). | Other Klim grotesques: Untitled Sans or National 2; or off-Klim: ABC Diatype (Dinamo), Aeonik (CoType). |
| Fontshare / ITF "starter pack" — Satoshi, General Sans, Clash Display, Cabinet Grotesk, Switzer, Space Grotesk (Indian Type Foundry, free) | Free + slick + on every dribbble shot since 2021; "Clash Display + Satoshi body" is now a *look*, not a choice. | Clash Display → Bricolage Grotesque (Mathieu Triay, OFL) or Anybody/Big Shoulders (OFL) for display · Satoshi/General Sans → Hanken Grotesk, Schibsted Grotesk, Instrument Sans · Space Grotesk → Departure Mono / Space Mono is fine but tired; try Spline Sans or Familjen Grotesk (OFL). |
The meta-rule: if the only justification for a face is "it's clean and modern," you have not made a decision. *Clean and modern* is the floor, not the brief.
1. Pick the Register Before the Font
Never name a typeface before you can name the register: the mood, era, industry, medium, and voice. The same word ("modern") points at five different faces depending on register. Work the framework below, then choose — and offer options at three budget tiers so money is never the excuse for a boring result.
> Budget tiers used throughout: Libre = free, OFL/Apache, self-hostable. PWYW/Trial = pay-what-you-want or generous free-for-personal trial (commercial use paid). Commercial = licensed foundry retail.
Warm editorial (magazines, long-form, "human and considered")
Libre: Newsreader (Production Type) for text + display; Source Serif 4 (Adobe) for body; Spectral (Production Type) for screen-first reading.
PWYW/Trial: Editorial New (Pangram Pangram) for narrow editorial headlines; Reckless (Displaay, trial).
Commercial: Tiempos Text/Headline (Klim); GT Sectra (Grilli Type) for that scalpel-and-broad-nib warmth; Lyon (Commercial Type).
Industrial / technical / engineering
Libre: IBM Plex (Sans/Mono/Serif, Bold Monday) — the most credible libre technical superfamily; Space Mono only if you want the retro-NASA wink.
PWYW/Trial: Basier (atipo, PWYW) for a tidy grotesque; Chaney (atipo) for a stencil-tech display edge.
Commercial: GT America (Grilli Type); ABC Monument Grotesk or ABC Diatype Mono (Dinamo); Akkurat (Lineto, Laurenz Brunner) — the original Swiss-spec workhorse.
Luxury / fashion / beauty
Libre: Cormorant (Christian Thalmann, OFL) — a Garamond-adjacent display with extreme delicacy; Libre Caslon Display (OFL) for high-contrast titling.
Commercial: National 2 (Klim); FF Meta or Stratos for signage-grade legibility.
Literary / bookish
Libre: EB Garamond (OFL) — a faithful Garamond; Cardo (OFL) for scholarly long-form; Newsreader for screen.
PWYW/Trial: Editorial New for the literary-cover register.
Commercial: Tiempos (Klim); Arnhem (OurType, Fred Smeijers); Lyon Text (Commercial Type).
Brutalist / raw / counterculture
Libre: Velvetyne's catalog is the motherlode — Fivo Sans, Pilowlava, Basteleur, Le Murmure (libre, made for exactly this); Redaction (Titus Kaphar & Forest Young, OFL) for a degraded-newspaper feel.
PWYW/Trial: Uncut.wtf's display section; Collletttivo (Apfel Grotezk, libre) for a deadpan grotesque.
Commercial: ABC Whyte / ABC Gravity (Dinamo); anything from OH no Type Co (Hobeaux, Vulf Mono).
Retro-future / 70s–80s / sci-fi
Libre: Departure Mono (OFL) for pixel-mono; Orbitron (OFL) sparingly; VTF Redaction for degraded-future.
PWYW/Trial: Cassannet Plus (atipo, art-deco geometric) for a Cassandre-era poster feel; Round 8 (atipo).
Commercial: Druk (Commercial Type) for compressed poster-future; ABC Gravity (Dinamo); Sharp Grotesk (Sharp Type) at its narrow widths.
Quiet Swiss / neo-grotesque restraint
Libre: Archivo (Omnibus-Type) for a grotesque with a sturdier spine than Inter; Hanken Grotesk for a humanist-Swiss compromise.
PWYW/Trial: Basier (atipo).
Commercial: Akkurat (Lineto); Untitled Sans (Klim); ABC Diatype (Dinamo); the genuine Neue Haas Grotesk (Monotype).
Playful consumer / lifestyle / DTC
Libre: Bricolage Grotesque (Mathieu Triay) — expressive, has wdth+opsz axes; Gabarito; Fredoka (OFL) only for genuinely childlike.
PWYW/Trial: Sfizia (atipo); Pangram Pangram's PP Mori / PP Neue Montreal (free to try).
Commercial: Covik Sans or Degular (OH no Type Co) — warm, lively, "organic over geometric"; Obviously (OH no Type Co) for a flexible width-axis display.
Academic / scientific / data-dense
Libre: IBM Plex superfamily (sans + serif + mono share a skeleton — ideal for papers/dashboards); STIX Two (OFL) for math; Source Serif 4 for body.
PWYW/Trial: Wotfard for UI chrome.
Commercial: Lexicon (Bram de Does) for the most refined scholarly serif money can buy; Tiempos for journals.
2. Pairing as Logic, Not Vibes
Pairing is a small set of rules. Apply them; don't gamble.
One workhorse + one voice. Pick a neutral, deep-weight workhorse to carry 90% of the words (body, UI, captions) and one expressive "voice" face for display/headlines. Trying to make *two* expressive faces coexist is how decks end up shouting.
Contrast by classification, harmonize by skeleton. Pair across *categories* (a humanist serif body with a grotesque display) so they're clearly different jobs — but check they share a *skeleton*: similar construction logic, similar proportions. A geometric serif fights a humanist sans.
Match x-heights, not point sizes. Two faces at the same font-size can look like different sizes. Compare lowercase x-heights and adjust with font-size or size-adjust. Mismatched x-height is the #1 tell of an amateur pairing.
The superfamily shortcut. When in doubt, use one family that ships sans + serif + mono on a shared skeleton: IBM Plex (libre), Source (Sans 3 / Serif 4 / Code Pro, libre), Recursive (libre, variable), or commercial superfamilies like Klim's National + a Klim serif, Lineto's families, or GT America + GT Sectra. Guaranteed harmony, zero pairing risk.
Same designer / same foundry. Faces from one hand often share spacing and rhythm. OH no Type Co's catalog inter-pairs; Klim faces inter-pair; Production Type's Newsreader + a Production sans.
Historical compatibility. Faces from one era share DNA (two didones; a Garalde with a humanist sans both rooted in calligraphic forms). Don't pair a 1490s Garalde with a 1990s techno display unless tension is the *point*.
Limit to two families. Three only if one is a mono used strictly for code/data. Past that you have chaos, not hierarchy — use weight, width, opsz, and case for variety within a family.
Quick worked pairings (none from the starter pack):
Reverse-contrast (thick horizontals, thin verticals — Western/circus/"Italian"): Le Murmure leans this way; OH no Type Co's display work explores it; commercial Caslon Doric-adjacent slab-reverse faces. Use as a deliberate jolt.
Blackletter-adjacent / textura without going full Gothic: rarely right outside metal/heritage/editorial pull-quotes — when you must, prefer a *modern interpretation* over a 1500s textura, and never set body copy in it.
4. The Libre Tier — No Budget Is No Excuse
(a) Interesting Google Fonts beyond the defaults
Google Fonts is not just Roboto and Open Sans. Reach for these instead:
Grotesques / sans: Bricolage Grotesque, Instrument Sans (+ Instrument Serif for the condensed-display partner), Hanken Grotesk, Schibsted Grotesk, Gabarito, Onest, Figtree, Familjen Grotesk, Archivo (+ Archivo Expanded/Narrow), Mona Sans / Hubot Sans (GitHub).
Caveat — already overused even though libre: Fraunces, Space Grotesk, Sora, and Plus Jakarta Sans. Fine faces, but if you use them you're swimming in the same pool as everyone else; treat them as *defaults to beat*, not destinations.
Velvetyne (velvetyne.fr) — France, since 2010. The most adventurous libre catalog: Le Murmure, Pilowlava, Basteleur, Fivo Sans, Redaction. Genuinely libre (use/modify/redistribute).
Collletttivo (collletttivo.it) — Milan, first Italian open-source foundry. Apfel Grotezk and friends.
The League of Moveable Type — the original open-source foundry (League Gothic, League Spartan, Ostrich Sans).
atipo foundry (atipofoundry.com) — Gijón, Spain. True pay-what-you-want (set your own price, including the minimum): Wotfard, Basier, Chaney, Round 8, Cassannet Plus, Sfizia, N27.
Uncut.wtf — curated catalog (~160+) of free/open-source contemporary type by independent designers (by Kasper Nordkvist). Best discovery surface for *current* libre work.
Open Foundry (open-foundry.com) — curated open-source typeface gallery, distraction-free specimens.
Fontshare / Indian Type Foundry (fontshare.com) — free for commercial use, high quality (Satoshi, General Sans, Clash Display, Switzer, Cabinet Grotesk). Caveat: several are now badly overused — treat as the AI starter pack and prefer the alternatives in §0.
> Free-to-try ≠ libre. Pangram Pangram and Displaay offer generous *trial / free-for-personal* fonts, but commercial use must be licensed. Don't ship a client site on a "free" trial weight.
5. Type Scales
Modular ratios
| Ratio | Name | Use case |
|---|---|---|
| 1.067 | Minor Second | Dense UIs, dashboards |
| 1.125 | Major Second | General web body content |
| 1.200 | Minor Third | Balanced default hierarchy |
| 1.250 | Major Third | Marketing, headline-forward |
| 1.618 | Golden Ratio | Classical; too large for most UI — use only for poster/display |
Pick the ratio to match the register: dense tools want a *small* ratio (1.125–1.2); a fashion landing page wants a *large* one (1.333+) so the display face can breathe.
Fluid type with clamp()
:root {
/* body: 16px @ 320px viewport → 20px @ 1240px */
--step-0: clamp(1rem, 0.91rem + 0.43vw, 1.25rem);
/* h2: 28px → 48px */
--step-3: clamp(1.75rem, 1.32rem + 2.14vw, 3rem);
}
/* Always use rem for the min/max so user zoom is respected (see §8). */
Generate the whole scale with a tool like Utopia (utopia.fyi) so the min and max sets share one ratio — don't hand-tune each step and drift out of rhythm.
Vertical rhythm
Set a baseline unit (e.g. 1.5rem = 24px), make spacing multiples of it, and let headings snap to integer multiples. Body line-height ~1.5–1.7; headings tighter (1.05–1.2). Never apply one global line-height.
6. Variable Fonts & Axes
| Axis | Tag | Typical range | Real use |
|---|---|---|---|
| Weight | wght | 100–900 | One file, many weights — animate or theme |
| Width | wdth | ~75–125 | Fit headlines to containers without re-tracking |
| Optical size | opsz | 8–144 | Correct contrast for size — auto via font-optical-sizing: auto |
| Slant | slnt | -12–0 | Oblique without a second file |
| Grade | GRAD | varies | Adjust apparent weight without reflow — perfect for dark mode |
Use opsz correctly: large display sizes want higher contrast, finer serifs, tighter spacing; small text wants the opposite. Faces like Newsreader and Bricolage Grotesque carry a real opsz axis — let the browser drive it with font-optical-sizing: auto, or set it explicitly per type level. Don't set a display opsz on body copy.
Dark-mode compensation with GRAD (no layout shift):
@media (prefers-color-scheme: dark) {
body { font-variation-settings: "GRAD" 50; } /* heavier-looking, same metrics */
}
If the face has no GRAD, nudge weight (400 → 450) — but know that *changes metrics* and can shift layout.
Exotic axes exist and are worth knowing per-face: Recursive ships a CASL (casual) and MONO axis; some Dinamo/variable display faces expose custom axes for serif-shape or "energy." Read the foundry's spec — never assume an axis tag.
7. Performance & Loading
Self-host WOFF2 for control and privacy; CDN only when you must. Google Fonts CSS adds a render-blocking round trip — if you use it, preconnect and prefer self-hosting the WOFF2.
Subset. Latin-only is ~30KB vs ~150KB+ full. Drop Cyrillic/Greek/Vietnamese you don't ship. Tools: glyphhanger, fonttools subset.
font-display: swap for body (show text immediately); optional for non-critical decorative faces to dodge CLS entirely.
Preload the one critical face:<link rel="preload" as="font" type="font/woff2" crossorigin>. Don't preload everything — that just competes for bandwidth.
Kill CLS with size-adjust + fallback metrics. Match the fallback's x-height/advance to the web font so the swap doesn't reflow:
@font-face {
font-family: "Hanken Fallback";
src: local("Arial");
size-adjust: 97%; /* tune to match the real face's x-height */
ascent-override: 92%;
descent-override: 24%;
line-gap-override: 0%;
}
body { font-family: "Hanken Grotesk", "Hanken Fallback", sans-serif; }
(Next.js next/font, Fontaine, and Capsize generate these overrides automatically — use them.)
Budget guide: Fast (<100KB, 2–3 WOFF2) · Balanced (100–200KB) · Rich (200–400KB). Prefer one variable file over eight static weights.
Never use @import for fonts (render-blocking, serialized) and never Font Awesome / icon fonts for icons — use inline SVG.
8. Accessibility — Non-Negotiable
These are hard rules, not suggestions:
Body / prose / caption text ≥ 14px (0.875rem). Never smaller. No text-xs on body; no 0.7–0.8rem on prose, captions, or meta.
Eyebrow / label text may sit at 12px ONLY if weight ≥ 600, uppercase, and letter-spacing ≥ 0.1em — so the *apparent* size reads larger. That's the only exception.
Never lock zoom. No user-scalable=no, no maximum-scale<2 in the viewport meta. Use <meta name="viewport" content="width=device-width, initial-scale=1"> and nothing that defeats pinch-zoom.
Use rem/em for body sizing, not px, so the user's browser font-size preference and zoom are honored. clamp() mins/maxes in rem.
WCAG 2.1 AA contrast: 4.5:1 body, 3:1 for large text (≥24px, or ≥18.66px bold). Never light-on-light or dark-on-dark.
Line spacing ≥ 1.5× body; paragraph spacing ≥ 2× font size; user must be able to override letter-spacing to 0.12em and word-spacing to 0.16em without breaking layout.
Measure 45–75 characters (65ch sweet spot). Cap prose width; don't let it run to the viewport edge on wide screens.
9. OpenType Features
/* Prefer the high-level properties; fall back to feature-settings only for ssXX/cvXX */
.tabular { font-variant-numeric: tabular-nums; } /* align numbers in tables */
.fractions { font-variant-numeric: diagonal-fractions; }/* 1/2 → ½ */
.smallcaps { font-variant-caps: all-small-caps; } /* acronyms, not faux caps */
.ligatures { font-variant-ligatures: common-ligatures; }
.brand { font-feature-settings: "ss01" 1, "cv05" 2; }/* stylistic alts — check the spec */
Use tabular numerals for any column of figures (prices, dashboards). Use the font's real small caps, never text-transform + smaller size (that's faux small caps — uneven weight). Stylistic sets (ssXX) are font-specific — read the foundry's glyph chart; don't blindly enable ss01.
10. Anti-Patterns
★ The AI-portfolio starter-pack look (headline anti-pattern)
What it looks like: a big soft display serif (Fraunces) + Inter body + acres of whitespace + one purple/teal accent gradient + Clash Display headers. Why it's wrong: it's the visual signature of "generated, not designed" — instantly dated, indistinguishable from ten thousand other sites. Instead: pick a *register* (§1), beat every default (§0), and let the type carry a point of view.
Picking a font before knowing the register
Choosing letters before you can name the mood/era/voice. You'll always reach for your habit. Decide the register first; the shortlist follows.
The system-font cop-out
font-family: -apple-system, ... shipped as the *final* brand decision because choosing was hard. Fine for a throwaway tool; a cop-out for anything with identity. (System stacks are a great *fallback*, not a brand.)
Faux bold / faux italic
Synthesizing weight or slant the family doesn't have (browser smearing the regular). Always load a real bold and real italic, or use a variable wght/slnt axis.
Too many families
3+ unrelated families = chaos. Two max (a mono for code can be the third). Get variety from weight/width/opsz/case.
Centered, long-measure body
Centering paragraphs longer than a couple lines, or letting measure exceed ~75ch. Both wreck readability — the eye loses the next line's start.
Ignoring x-height matching
Pairing or swapping faces without comparing x-heights → visible size mismatch and CLS. Compare lowercase, tune with size-adjust.
Weight jumps too harsh
400 body → 700 heading at large sizes can clang. For subtle hierarchy try 400/600 or 380/520; reserve the big jump for genuinely loud display.
Global single line-height & fixed px sizes
One line-height: 1.5 everywhere, or hardcoded px body. Set line-height per level; size in rem with clamp().
Loading full character sets
Shipping Cyrillic/Greek/Vietnamese to an English-only site. Subset.
11. Licensing Literacy
Get this right before you ship — a wrong license is a legal and a reputational problem.
SIL OFL (Open Font License): the libre standard (most Google Fonts, Adobe Source family, IBM Plex, Velvetyne, Collletttivo). Use commercially, embed, self-host, and modify/redistribute (under the same license, can't sell the font itself alone). Safe default for products.
Apache 2.0: also permissive (Roboto, Inter historically) — fine commercially; fewer redistribution stipulations than OFL.
Commercial EULA: retail foundries (Klim, Commercial Type, Grilli Type, Dinamo, Sharp Type, OH no Type Co, Colophon, Lineto, Optimo, Production Type retail, MCKL, Displaay retail) license by use type, often separately:
Desktop (install + design comps/print) — usually priced by # of workstations.
Web (@font-face self-host) — priced by monthly pageviews or flat. Self-host vs foundry-hosted matters: some require their CDN; others let you host the WOFF2.
App / embedded — apps, ebooks, software UI, broadcast, logos — almost always a *separate, often larger* license. A web license does not cover an iOS app.
Trial / free-for-personal: Pangram Pangram, Displaay, and many foundries give free weights for *non-commercial* use (portfolios, pitches). Commercial use must be paid. "Free to try" ≠ libre.
PWYW: atipo lets you name a price (incl. their minimum) for full commercial rights — genuinely the best value tier when libre won't do.
Foundry-hosted vs self-host: foundry-hosted webfont services (Adobe Fonts, Monotype, Fontstand) bundle licensing but tie you to their CDN/subscription and can vanish if you lapse. Self-hosting OFL/PWYW/bought-web WOFF2 is the durable choice for products you'll maintain.
Always read the specific EULA. "We saw it on Pinterest" is not a license. Verify desktop/web/app coverage, pageview tier, and modification rights before committing a brand to a face.
12. Integration with Other Skills
design-system-creator — emit type tokens (scale, line-height, tracking, axis defaults).
web-design-expert — implement the chosen system in layout.
vibe-matcher — translate a brand mood into a §1 register before selecting.