Help us improve
Share bugs, ideas, or general feedback.
Guides web typography with 2-3 font family limits, modular scales (Minor Third, Major Third, Perfect Fourth), line heights (1.4-1.6 body, 1.1-1.3 headings), and 45-75 character line lengths per Bringhurst rules.
npx claudepluginhub oborchers/fractional-cto --plugin visual-design-principlesHow this skill is triggered — by the user, by Claude, or both
Slash command
/visual-design-principles:typographyThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Typography accounts for 95% of web design (Oliver Reichenstein, iA). A correct type system makes every page look intentional. A broken one makes every page look amateur — regardless of color, imagery, or layout.
Creates modular typography scales with size ratios, weights, line-heights, responsive adjustments, and best practices for consistent UI text.
Designs accessible typography systems using relative units, scalable type scales, and user-override-safe spacing. Useful for setting font sizes, line heights, and ensuring WCAG readability compliance.
Designs a typographic system with modular scale, baseline grid, and contrast rules for clear visual hierarchy. Use when building a type system for websites, brands, or documents.
Share bugs, ideas, or general feedback.
Typography accounts for 95% of web design (Oliver Reichenstein, iA). A correct type system makes every page look intentional. A broken one makes every page look amateur — regardless of color, imagery, or layout.
Limit every project to 2-3 font families maximum. More than three creates visual noise and increases page weight.
Pairing strategy — contrast, not similarity:
| Pairing Type | Heading | Body | Example |
|---|---|---|---|
| Serif + Sans-serif | Playfair Display | Inter | Editorial, marketing |
| Geometric + Humanist | Poppins | Source Sans Pro | SaaS, dashboards |
| Monospace + Sans-serif | JetBrains Mono | Inter | Developer tools |
| Single family | Inter (bold) | Inter (regular) | Minimal, utilitarian |
The single-family approach (one typeface, varied weights) is the safest choice for applications. It guarantees harmony and reduces load time.
Define font sizes using a mathematical ratio, not arbitrary values. Multiply the base size by the ratio for each step.
Base size: 16px (1rem). Never go below 16px for body text on screens.
| Scale Name | Ratio | Sizes from 16px base |
|---|---|---|
| Minor Third | 1.200 | 16 / 19.2 / 23.0 / 27.6 / 33.2 |
| Major Third | 1.250 | 16 / 20 / 25 / 31.3 / 39.1 |
| Perfect Fourth | 1.333 | 16 / 21.3 / 28.4 / 37.9 / 50.5 |
| Golden Ratio | 1.618 | 16 / 25.9 / 41.9 / 67.8 / — |
Selection guide: Use Minor Third for dense UIs (dashboards, admin panels). Use Major Third or Perfect Fourth for content-heavy pages. Use Golden Ratio sparingly — only for dramatic editorial layouts.
| Context | Line Height | Reason |
|---|---|---|
| Body text | 1.4–1.6 | Optimal readability per Bringhurst |
| Headings | 1.1–1.3 | Tighter to maintain visual weight |
| ALL CAPS text | 1.0–1.2 | Caps are uniform height; needs less leading |
| Small/caption text | 1.5–1.7 | Smaller text needs proportionally more space |
Add letter-spacing: 0.05em–0.1em to ALL CAPS text to compensate for reduced legibility.
Optimal: 45–75 characters per line. The ideal is 66 characters (Bringhurst). Lines shorter than 45 characters cause excessive eye jumps. Lines longer than 75 characters cause readers to lose their place.
Implementation: Set max-width: 65ch on text containers. The ch unit is based on the width of the "0" character, making it font-aware.
clamp()Replace media-query-based font scaling with clamp() for fluid sizing between breakpoints.
Formula: clamp(min, preferred, max) where preferred uses viewport units.
| Element | clamp() Value |
|---|---|
| Body | clamp(1rem, 0.95rem + 0.25vw, 1.125rem) |
| H3 | clamp(1.25rem, 1rem + 1vw, 1.75rem) |
| H2 | clamp(1.5rem, 1.2rem + 1.5vw, 2.25rem) |
| H1 | clamp(2rem, 1.5rem + 2vw, 3.5rem) |
| Display | clamp(2.5rem, 2rem + 3vw, 5rem) |
Optimize font delivery to prevent layout shift and invisible text:
font-display: swap — show fallback text immediately, swap when font loads<link rel="preload" as="font" type="font/woff2" crossorigin>| Anti-Pattern | Why It Fails | Fix |
|---|---|---|
| More than 3 font families | Visual noise, slow load times | Limit to 2-3; prefer single-family with weight variation |
| No type scale (arbitrary sizes) | Inconsistent hierarchy; sizes feel random | Adopt a modular scale ratio |
| Body text below 16px | Unreadable on mobile; fails accessibility | Minimum 16px (1rem) for body |
| Thin font weights (100-200) at small sizes | Disappears on low-DPI screens | Use 400+ for body, 300 minimum at 18px+ |
| Line length exceeding 75 characters | Readers lose their place between lines | Set max-width: 65ch on text containers |
No font-display strategy | Flash of invisible text (FOIT) | Always set font-display: swap |
Working implementations in examples/:
examples/type-scale-and-pairing.md — Complete modular type scale in CSS custom properties, Tailwind configuration, and React heading component with responsive sizingWhen reviewing or building typographic systems:
max-width: 65ch or equivalent)clamp() instead of breakpoint-only scalingfont-display: swap<head>