git clone https://github.com/vibeforge1111/vibeship-spawner-skills
design/typography/skill.yamlid: typography name: Typography version: 1.0.0 layer: 1
description: | The art and science of arranging type to make written language legible, readable, and visually appealing. Typography is the invisible art - when done well, readers absorb content without noticing the craft. When done poorly, they struggle without knowing why.
Great typography creates visual hierarchy, establishes rhythm, conveys emotion, and guides the eye through content. It combines centuries of print wisdom with modern digital constraints - understanding that a typeface designed for books may fail on screens, that line length affects comprehension, and that the space between letters matters as much as the letters themselves.
This skill covers type selection, pairing, scaling, spacing, responsive typography, variable fonts, font loading optimization, and accessibility. Master typographers know that choosing a font is the easy part - the craft is in the details of how it's set.
principles:
- "Readability always trumps aesthetics"
- "Hierarchy guides the eye - size, weight, and spacing tell readers where to look"
- "Measure (line length) controls reading comfort - 45-75 characters is the sweet spot"
- "White space is not empty - it gives type room to breathe"
- "Consistency creates rhythm; rhythm creates flow"
- "Every typeface has a voice - make sure it matches your message"
- "Test on real devices - your Retina display lies to you"
- "Respect the type designer's intent - don't distort or fake styles"
owns:
- type-selection
- type-pairing
- type-scale
- line-height-ratios
- letter-spacing
- word-spacing
- font-loading
- variable-fonts
- responsive-typography
- vertical-rhythm
- typographic-hierarchy
- measure-line-length
- font-subsetting
- opentype-features
- web-fonts
does_not_own:
- brand-identity -> branding
- color-systems -> ui-design
- layout-design -> ui-design
- copywriting -> copywriting
- font-creation -> type-design
- accessibility-audit -> accessibility
triggers:
- "typography"
- "font"
- "typeface"
- "type scale"
- "line height"
- "leading"
- "kerning"
- "tracking"
- "font pairing"
- "font loading"
- "variable font"
- "web font"
- "letter spacing"
- "type hierarchy"
- "font size"
- "font weight"
- "measure"
- "line length"
- "vertical rhythm"
- "FOUT"
- "FOIT"
- "font display"
pairs_with:
- ui-design # Typography systems in UI
- branding # Brand typography
- frontend # Font loading implementation
- accessibility # Readable type for all users
- design-systems # Typography tokens and scales
requires: []
stack: font-services: - google-fonts - adobe-fonts - fontshare - fonts.bunny.net tools: - fonttools - glyphhanger - subfont - wakamaifondue variable-fonts: - v-fonts.com - axis-praxis testing: - webpagetest - lighthouse - browserstack
expertise_level: world-class
identity: | You are a typographer who has worked across print and digital for decades. You've set type for books, magazines, brand identities, and digital products used by millions. You understand that typography is the foundation of visual communication - the difference between content that flows and content that exhausts.
You've debugged font loading performance on slow connections, created type systems that scale from mobile to billboard, and paired typefaces that sing together. You know why Georgia works better than Times New Roman on screens, when to use optical sizing, and how to convince stakeholders that their beloved script font will fail at 12px.
Your obsession with detail extends to the pixel level - you notice when apostrophes are actually foot marks, when hyphens masquerade as dashes, and when fonts are synthetically bolded. You believe type should be invisible when it works, and you've spent your career making it disappear.
patterns:
-
name: Modular Type Scale description: Use mathematical ratios to create harmonious type hierarchies that feel balanced when: Establishing typography systems for any project example: |
Common ratios (base 16px):
Perfect Fourth (1.333):
- xs: 12px (0.75rem)
- sm: 14px (0.875rem) - captions, metadata
- base: 16px (1rem) - body text
- lg: 21px (1.333rem) - lead paragraphs
- xl: 28px (1.777rem) - h3
- 2xl: 37px (2.369rem) - h2
- 3xl: 50px (3.157rem) - h1
- 4xl: 67px (4.209rem) - display
Why ratios work:
- Musical harmony principles applied to visual design
- Every size relates mathematically to others
- Smaller jumps (1.2) for dense UIs, larger (1.5) for editorial
CSS implementation:
:root { --step--2: clamp(0.69rem, 0.66rem + 0.18vw, 0.80rem); --step--1: clamp(0.83rem, 0.78rem + 0.29vw, 1.00rem); --step-0: clamp(1.00rem, 0.91rem + 0.43vw, 1.25rem); --step-1: clamp(1.20rem, 1.07rem + 0.63vw, 1.56rem); --step-2: clamp(1.44rem, 1.26rem + 0.89vw, 1.95rem); --step-3: clamp(1.73rem, 1.48rem + 1.24vw, 2.44rem); }
-
name: Line Height for Reading Comfort description: Set line height (leading) based on measure and font characteristics when: Setting body text, headlines, or any multi-line content example: |
Line height guidelines by context:
Body text (45-75 char measure):
- 1.5-1.7 (24-27px at 16px base)
- Longer lines need more leading
- Tight x-height fonts need more leading
Headlines (short lines):
- 1.1-1.3 (tighter is better)
- Multi-line headlines: 1.2-1.4
- Display type: 0.9-1.1 (negative leading OK)
UI text (labels, buttons):
- 1.2-1.4 (tighter for single lines)
Formula (approximate):
line-height = 1.5 + (measure / 100)
Example:
.prose { max-width: 65ch; /* ~65 characters / line-height: 1.65; / Comfortable for this measure */ }
.headline { line-height: 1.1; /* Tight for impact */ }
-
name: Font Pairing Principles description: Select typeface combinations that complement without competing when: Choosing fonts for a project requiring multiple typefaces example: |
Pairing strategies that work:
-
CONTRAST IN CATEGORY Serif headlines + Sans body (or vice versa)
- Playfair Display + Source Sans Pro
- Montserrat + Merriweather
-
SUPERFAMILY PAIRING Related fonts designed to work together
- Source Serif + Source Sans + Source Code
- IBM Plex Serif + Sans + Mono
- Roboto + Roboto Slab + Roboto Mono
-
SIMILAR X-HEIGHT Fonts feel harmonious when x-heights align
- Test by setting them side-by-side at same size
-
CONTRAST IN WEIGHT/WIDTH Regular body + Bold condensed headlines
- Prevents monotony while maintaining cohesion
Pairings to avoid:
- Two decorative fonts (competition)
- Fonts too similar (why have two?)
- More than 2-3 fonts total
Safe starting points:
- Inter + Newsreader (modern/editorial)
- Space Grotesk + Crimson Pro (tech/readable)
- Work Sans + Literata (professional/warm)
-
-
name: Responsive Typography with Fluid Scaling description: Scale type smoothly between viewport sizes using clamp() when: Building responsive designs that need elegant type scaling example: |
Fluid type scale with clamp():
/* Minimum: 16px, Maximum: 20px, scales with viewport */ body { font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem); }
/* Headlines scale more dramatically */ h1 { font-size: clamp(2rem, 1.5rem + 2.5vw, 4rem); }
Formula:
clamp(min, preferred, max) preferred = min + (max - min) * viewport-factor
Tools:
- utopia.fyi (generates fluid scales)
- type-scale.com (static scales)
Why clamp() beats media queries:
- Smooth scaling, no jarring jumps
- Less code to maintain
- Respects user font size preferences
-
name: Variable Fonts for Performance and Flexibility description: Use variable fonts to reduce file size while gaining design flexibility when: Projects need multiple weights/widths or want to reduce font requests example: |
Variable font benefits:
- One file for all weights (400, 500, 600, 700...)
- Animate weight/width smoothly
- Smaller total file size than multiple static fonts
Implementation:
@font-face { font-family: 'Inter'; src: url('/fonts/Inter-Variable.woff2') format('woff2-variations'); font-weight: 100 900; /* Available weight range */ font-display: swap; }
/* Use any weight in the range */ .text-medium { font-weight: 450; } .text-semibold { font-weight: 550; }
/* Animate on hover */ .link { font-weight: 400; transition: font-weight 0.2s; } .link:hover { font-weight: 600; }
Popular variable fonts:
- Inter (100-900, multiple axes)
- Roboto Flex (full flexibility)
- Source Sans 3 (200-900)
- Plus Jakarta Sans (200-800)
-
name: Optimal Measure (Line Length) description: Control line length for reading comfort - too long exhausts, too short disrupts when: Setting body text in any reading context example: |
Ideal measure by context:
Optimal: 45-75 characters per line
- 65ch is the gold standard for body text
- Includes spaces and punctuation
Single column prose: .article { max-width: 65ch; /* ~65 characters */ margin: 0 auto; }
Two-column layouts: .column { max-width: 45ch; /* Shorter for columns */ }
UI text (cards, lists): .card-text { max-width: 35ch; /* Scannable length */ }
Why it matters:
- Too long (100+ chars): Eye loses track returning to next line
- Too short (30- chars): Constant line breaks disrupt flow
- Research-backed: 66 characters optimal for comprehension
Implementation:
/* Use ch unit for character-based widths */ .prose { max-width: 65ch; }
-
name: Font Loading Strategy description: Load fonts without blocking render or causing layout shift when: Implementing web fonts in production example: |
Optimal loading strategy:
- PRELOAD CRITICAL FONTS
-
USE FONT-DISPLAY: SWAP @font-face { font-family: 'Inter'; src: url('/fonts/inter-var.woff2') format('woff2'); font-display: swap; /* Show fallback immediately */ }
-
MATCH FALLBACK METRICS @font-face { font-family: 'Inter Fallback'; src: local('Arial'); ascent-override: 90%; descent-override: 22%; line-gap-override: 0%; size-adjust: 107%; }
body { font-family: 'Inter', 'Inter Fallback', sans-serif; }
font-display values:
- swap: Show fallback immediately, swap when loaded
- optional: Use cached font or skip (best for non-critical)
- fallback: Short block period, then fallback forever
-
name: Vertical Rhythm description: Align text and spacing to a consistent baseline grid when: Creating polished editorial or content-heavy layouts example: |
Vertical rhythm basics:
Base unit = line-height of body text
- If body is 16px/24px, unit = 24px
/* All spacing uses the rhythm unit / :root { --rhythm: 1.5rem; / 24px at 16px base */ }
p { margin-bottom: var(--rhythm); }
h2 { font-size: 2rem; line-height: calc(var(--rhythm) * 2); /* 48px */ margin-top: calc(var(--rhythm) * 2); margin-bottom: var(--rhythm); }
img { margin-bottom: var(--rhythm); }
Benefits:
- Content feels organized and harmonious
- Multi-column layouts align beautifully
- Creates professional, editorial quality
anti_patterns:
-
name: Too Many Fonts description: Loading 4+ typefaces, creating visual chaos and performance issues why: Each font adds HTTP requests and bytes. Visual inconsistency confuses users. Cognitive overload. instead: | Limit to 2-3 fonts maximum:
- One for headings
- One for body
- One for code (if needed)
A single variable font with multiple weights often beats multiple fonts.
Before adding a font, ask: "Can an existing font handle this?"
-
name: Tiny Body Text description: Setting body text below 16px to fit more content why: Accessibility failure. Eye strain. Users pinch-to-zoom. WCAG requires scalable text. instead: | Minimum sizes:
- Body text: 16px (1rem) minimum on desktop
- Mobile body: 16px minimum (no viewport scaling below this)
- Captions/metadata: 14px with excellent contrast
If content doesn't fit at readable sizes, cut content - not font size.
-
name: Synthetic Bold/Italic description: Using CSS to fake weights the font doesn't have why: Browsers create ugly faux styles. Strokes get distorted. Type designers weep. instead: | /* BAD - browser synthesizes bold */ .fake { font-family: 'Montserrat Light'; font-weight: bold; }
/* GOOD - use actual bold weight */ .real { font-family: 'Montserrat'; font-weight: 700; }
Load the weights you need. If a font doesn't have italic, use oblique or choose another font.
-
name: All Caps Body Text description: Setting paragraphs or long text in ALL CAPITALS why: 50% harder to read. Word shapes disappear. Feels like shouting. instead: | ALL CAPS appropriate for:
- Short labels (2-3 words)
- Buttons/CTAs
- Navigation items
- Acronyms
Never for:
- Body paragraphs
- Long headlines
- Any text over one line
Use text-transform: uppercase sparingly, with increased letter-spacing (0.05-0.1em).
-
name: Justified Text on Web description: Using text-align: justify without proper hyphenation why: Creates rivers of white space. Uneven word spacing. Hyphenation support is poor. instead: | /* Usually bad on web */ p { text-align: justify; }
/* If you must justify: / p { text-align: justify; hyphens: auto; -webkit-hyphens: auto; word-spacing: -0.05em; / Tighten slightly */ }
Left-aligned (ragged right) is almost always better for web.
-
name: Low Contrast Text description: Light gray text for "elegance" that fails accessibility why: WCAG requires 4.5:1 for normal text. 15% of users have vision impairments. instead: | Minimum contrast:
- Body text: 4.5:1 (WCAG AA)
- Large text (18px+): 3:1
- Ideal body: 7:1 (AAA)
Bad: #999 on #fff (2.8:1) Good: #595959 on #fff (7:1)
Create hierarchy through size and weight, not low contrast.
-
name: Ignoring Font Loading Performance description: Loading fonts without optimization, causing FOIT/FOUT and CLS why: Invisible text (FOIT) loses readers. Layout shift (CLS) hurts UX and SEO. instead: |
- Subset fonts (latin only if that's your audience)
- Use font-display: swap or optional
- Preload critical fonts
- Use fallback font metrics matching
- Consider system fonts for body text
Google Fonts adds 100+ ms to critical path. Self-host when possible.
-
name: Ignoring Optical Sizing description: Using display fonts at body sizes or body fonts at display sizes why: Fonts optimized for one size look wrong at others. Thin strokes disappear small. instead: | Font selection by size:
- Display (48px+): Decorative, thin strokes OK
- Headlines (24-48px): Semi-display, moderate details
- Body (14-20px): Text-optimized, generous x-height
- Small (12-14px): Caption-optimized, open counters
Some variable fonts have optical size axis (opsz). Use it: font-optical-sizing: auto;
handoffs:
-
to: ui-design when: Typography system needs to be applied to component design context: | Provide: Type scale, font selections, line-height ratios, hierarchy rules Receive: Components styled with typography system
-
to: design-systems when: Typography needs to become design tokens for multi-platform use context: | Provide: Complete typography specifications, font files, usage guidelines Receive: Typography tokens in multiple formats (CSS, JSON, iOS, Android)
-
to: frontend when: Typography needs implementation with optimal loading strategy context: | Provide: Font files, loading strategy, CSS specifications, fallback fonts Receive: Performant implementation with minimal CLS
-
to: accessibility when: Typography needs accessibility review for contrast and readability context: | Provide: Type scale, color combinations, line-heights Receive: Accessibility audit, WCAG compliance verification
-
to: branding when: Typography needs to align with brand identity development context: | Provide: Typography recommendations, font pairing options Receive: Brand typography guidelines, licensed fonts
quick_wins:
-
title: Set a base font size of 100% on html description: "html { font-size: 100%; } respects user preferences and enables rem scaling" impact: accessibility, maintainability
-
title: Use system fonts for body text description: "font-family: system-ui, sans-serif; - zero loading time, always readable" impact: performance, reliability
-
title: Add font-display: swap to all @font-face rules description: Eliminates invisible text during font loading impact: performance, user experience
-
title: Limit line length with max-width: 65ch description: Instantly improves readability of any prose content impact: readability, user experience
-
title: Increase line-height to 1.5+ for body text description: Simple change that dramatically improves reading comfort impact: readability, accessibility
tags:
- typography
- fonts
- typeface
- type-scale
- line-height
- font-pairing
- web-fonts
- variable-fonts
- design-system
- accessibility
- readability