Typography & Fonts
Master font-family, system font stacks, Google Fonts, font-size (px vs rem), line-height, letter-spacing, and readable web typography.
🎯 What You Will Master in This Lesson
📐 The 3 Pillars of Professional Web Typography
More than 90% of information on the web is written language. Professional typography isn't just picking a pretty font — it's mathematical hierarchy:
- Line-Height: Tight (`1.15` to `1.25`). Large text needs less line-height or it drifts apart.
- Letter-Spacing: Negative (`-0.02em` to `-0.03em`). Removes gaping optical holes between big letters.
- Wrapping:
text-wrap: balance;to kill single-word orphan lines.
- Line-Height: Relaxed (`1.6` to `1.75`). Gives the eye comfortable breathing room.
- Line Length:
max-width: 65ch;(45–75 characters per line). Prevents horizontal eye fatigue. - Font-Size:
1rem(16px default) to1.125remfor long essays.
- Letter-Spacing: Positive (`0.08em` to `0.15em`). Uppercase letters crowd together without tracking!
- Transform:
text-transform: uppercase;(never capitalize raw HTML). - Font-Weight: Bold (`700` or `800`) to maintain punchy clarity at small sizes.
⚡ The Zero-KB System Font Stack: GitHub, Stripe & Apple Secret
Heavy web fonts (like downloading 4 weights of Roboto or Poppins) add 300KB+ of network payload and delay page rendering. Many of the fastest tech companies use the Native System UI Stack:
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}• macOS / iOS: Displays San Francisco (the crisp native Apple typeface).
• Windows 10 / 11: Displays Segoe UI (the native Microsoft Windows font).
• Android: Displays Roboto (native Google OS font).
• Linux: Displays Ubuntu or clean system sans-serif.
💻 Live Typography Hierarchy Playground
💎 Production CSS Micro-Typography Superpowers
These three underappreciated CSS properties separate polished Silicon Valley apps from beginner websites:
font-variant-numeric: tabular-nums;In standard fonts, `1` is narrow and `0` is wide. When counting or updating timers, the entire card shakes! `tabular-nums` locks all digits to monospaced widths without changing the rest of the font.
-webkit-line-clamp: 3;Truncates long blog snippets at exactly 3 lines with an automatic `...` ellipsis. Replaces fragile JavaScript substring truncation that chops off words in mid-sentence!
text-wrap: balance;Browsers traditionally wrap words greedy-first, leaving single orphan words stranded on row 2. `text-wrap: balance` balances the lines into equal, aesthetically pleasing widths.
Line-by-Line Code Breakdown
.category-badge { letter-spacing: 0.12em; text-transform: uppercase; }Expands the letter spacing by 12% of the font size. Small all-caps labels require extra tracking so the letters don't blend together into an illegible blur.
.article-title { line-height: 1.25; letter-spacing: -0.02em; }Tightens the headline. Large bold text (24px+) carries natural whitespace around its letterforms; tightening line-height and tracking produces a modern, punchy visual anchor.
.article-lead { line-height: 1.65; }Unitless line-height for body copy. Guarantees 65% additional breathing space between lines so readers' eyes smoothly track back to the start of the next line.
Q1Why is a unitless line-height multiplier (e.g. `line-height: 1.6;`) strictly preferred over fixed units like `line-height: 24px;` in design systems?
Q2Why do financial platforms like Stripe, Robinhood, and Bloomberg rely heavily on `font-variant-numeric: tabular-nums;`?
Q3What is the key performance difference between `font-display: swap;` and `font-display: optional;`?
Q4What modern CSS property automatically prevents single lonely 'orphan' words at the end of headings without requiring manual `<br>` tags?
Practice Challenge: Polish the Card Typography
In the live code editor on the right:
- Step 1: In
.article-title, add modern headline balancing:text-wrap: balance;. - Step 2: In
.article-lead, implement 2-line clamping: adddisplay: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;. - Step 3: In the HTML, duplicate paragraph text to make it 5 lines long, and observe how the browser cleanly truncates it with an ellipsis on line 2!
- Step 4: In
body, add-webkit-font-smoothing: antialiased;to test sub-pixel rendering.
💡 Click to view the completed typography rules
Common Pitfalls & Senior Developer Interview Questions
❌ Pitfall: The Cumulative Layout Shift (CLS) Font Trap
When using heavy web fonts without size adjustments, the fallback font renders with different letter widths. When the web font finally loads 2 seconds later, every paragraph jumps, causing horrible Cumulative Layout Shift (CLS) that tanks your Google Core Web Vitals score! Use modern size-adjust, ascent-override, and font-display: optional to match fallback metrics.
✅ Pro Tip: Variable Fonts Save 80% Network Bandwidth
Instead of loading 5 separate font files for regular (400), medium (500), semi-bold (600), bold (700), and black (900), use a single Variable Font (e.g. `InterVariable.woff2`). One single 40KB file gives you every possible weight from 100 to 900 and custom optical sizing!
💬 Interview Q: What is FOIT vs FOUT, and how does `font-display` solve the problem?
FOIT (Flash of Invisible Text): The browser hides text completely until the custom web font finishes downloading (often up to 3 seconds on cellular data), showing empty blank white blocks.
FOUT (Flash of Unstyled Text): The browser displays fallback system fonts immediately, then flashes and swaps to the custom font once ready.
font-display: swap; prioritizes content accessibility by guaranteeing FOUT over FOIT — users can read the article immediately while fonts load in the background.
💬 Interview Q: Why is `font-variant-numeric: tabular-nums` essential in SaaS dashboards?
In standard proportional fonts, numbers have varying glyph widths (the character ‘1’ is half as wide as ‘8’).
In real-time SaaS dashboards (crypto charts, stopwatch timers, financial invoices), every time a digit changes from 1 to 2, the total text string width changes by several pixels. This causes rapid, nauseating horizontal shaking. tabular-nums forces all digit glyphs to share the exact same width, freezing the layout rock-solid.
💬 Interview Q: How do you achieve true fluid typography across all screen sizes without media queries?
Using CSS clamp(min, preferred, max) with viewport width combined with a rem base:
font-size: clamp(1.25rem, 2vw + 1rem, 2.5rem);On mobile, it clamps safely at 1.25rem (20px). As the screen widens, it smoothly scales with the viewport (2vw). On giant 4K monitors, it safely caps at 2.5rem (40px) without ever overflowing.