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.
npx skills add https://github.com/curiositech/some_claude_skills --skill typography-expert
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.
✅ Use for:
clamp())wght, wdth, opsz, slnt, GRAD)font-display, self-host vs CDN, size-adjust fallback metrics to kill CLS)❌ Do NOT use for:
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.
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.
Pairing is a small set of rules. Apply them; don't gamble.
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.Quick worked pairings (none from the starter pack):
Genuinely interesting faces per class, with the people/foundries behind them. Mix of libre (L) and commercial (C). Use this to escape your defaults.
Calligraphic roots, modulated strokes, open apertures — warm and readable.
The "neutral" Swiss line (Helvetica/Akzidenz tradition) — but pick a *good* one.
Bauhaus circles-and-lines (Futura lineage).
Earlier, grittier grotesques and mechanical gothics.
1490s–1600s humanist roots, low contrast, bracketed serifs, angled stress.
18th-c., higher contrast, more vertical stress (Baskerville/Times lineage).
Extreme thick/thin contrast, hairline serifs (Bodoni/Didot lineage).
Heavy, often unbracketed rectangular serifs.
Chiseled, flared terminals — stone-cut feel, between serif and sans.
Warmer, lower-contrast text serifs built for reading on screen.
Big, characterful, headline-only.
For code, data, and the technical register.
Google Fonts is not just Roboto and Open Sans. Reach for these instead:
> 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.
| 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.333 | Perfect Fourth | Hero sections, bold statements |
| 1.414 | Augmented Fourth | Editorial drama |
| 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.
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.
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.
| 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.
preconnect and prefer self-hosting the WOFF2.glyphhanger, fonttools subset.font-display: swap for body (show text immediately); optional for non-critical decorative faces to dodge CLS entirely.<link rel="preload" as="font" type="font/woff2" crossorigin>. Don't preload everything — that just competes for bandwidth.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.
These are hard rules, not suggestions:
text-xs on body; no 0.7–0.8rem on prose, captions, or meta.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.clamp() mins/maxes in rem./* 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.
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.
Choosing letters before you can name the mood/era/voice. You'll always reach for your habit. Decide the register first; the shortlist follows.
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.)
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.
3+ unrelated families = chaos. Two max (a mono for code can be the third). Get variety from weight/width/opsz/case.
Centering paragraphs longer than a couple lines, or letting measure exceed ~75ch. Both wreck readability — the eye loses the next line's start.
Pairing or swapping faces without comparing x-heights → visible size mismatch and CLS. Compare lowercase, tune with size-adjust.
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.
One line-height: 1.5 everywhere, or hardcoded px body. Set line-height per level; size in rem with clamp().
Shipping Cyrillic/Greek/Vietnamese to an English-only site. Subset.
Get this right before you ship — a wrong license is a legal and a reputational problem.
@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.*The typeface is a decision, not a default. If you can't say why this face and not its three nearest neighbors, you haven't chosen yet.*
Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts.
Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts.
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
Set up Tailwind CSS v4 in Expo with react-native-css and NativeWind v5 for universal styling
Use Expo DOM components to run web code in a webview on native and as-is on web. Migrate web code to native incrementally.
Take curiositech/typography-expert from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.