Typography, Web Fonts & Variable Fonts
Typography makes up over 90% of the web's content. Mastering web typography requires balancing visual hierarchy, readability, performance, and responsive scaling across devices.
1. The Core Typography Stackβ
CSS provides properties to control every aspect of text rendering.
ββββββββββββββββββββββββββββββββββββββββββββ
β Line Height β
β ββββββββββββββββββββββββββββββββββββββ β
β β Font Size β β
β β ββββββββββββββββββββββββββββββββ β β
β β β Letter Spacing (Tracking) β β β
β β β βββββββββββββββββββββββββ β β β
β β β β CodeHarborHub Text β β β β
β β β βββββββββββββββββββββββββ β β β
β β ββββββββββββββββββββββββββββββββ β β
β ββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββ
Core Property Referenceβ
| Property | Typical Values | Best Practice / Rule |
|---|---|---|
font-family | System stacks, Custom web fonts | Always supply generic fallbacks (sans-serif, serif, monospace). |
font-size | rem, em, px, clamp() | Use rem for accessibility so user browser zoom preferences are respected. |
line-height | Unitless multiplier (e.g., 1.5, 1.2) | Avoid fixed px values. Use 1.2β1.3 for headings and 1.5β1.6 for body copy. |
font-weight | 100 to 900, bold, normal | Ensure custom web fonts support every declared weight. |
letter-spacing | em, px | Tighten large headings (-0.02em); widen small uppercase text (0.05em). |
2. System Font Stacks vs. Custom @font-faceβ
System Font Stacksβ
System stacks load instantaneously with zero network overhead because they rely on pre-installed operating system fonts.
/* Modern Clean System Sans-Serif Stack */
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
}
Loading Web Fonts with @font-faceβ
Custom web fonts require explicit @font-face definitions. Always prioritize modern, compressed web formats like WOFF2.
@font-face {
font-family: 'Geist';
src: url('/fonts/geist-regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap; /* Prevents Invisible Text (FOIT) */
}
- swap: Renders fallbacks immediately and swaps to the web font once loaded (minimizes render blocking).
- optional: Gives the browser a tiny window to download the font; if missed, it stays on the fallback for that session.
3. Modern Variable Fontsβ
Variable Fonts store multiple typographic variations (weight, width, slant, optical size) within a single file, replacing the need to load multiple static font files (regular.woff2, bold.woff2, italic.woff2).
/* Loading a single variable font file supporting weights 100 through 900 */
@font-face {
font-family: 'Inter Variable';
src: url('/fonts/inter-variable.woff2') format('woff2-variations');
font-weight: 100 900;
}
.heading-dynamic {
font-family: 'Inter Variable', sans-serif;
/* Precise numeric weight adjustment */
font-weight: 650;
/* Fine-tuning axis properties */
font-variation-settings: 'wght' 650, 'slnt' -5;
}
4. Fluid Typography with clamp()β
Instead of managing font sizes across multiple @media breakpoint rules, use the mathematical clamp() function for responsive fluid typography.
h1 {
/* Min: 2rem (32px), Preferred: 5vw, Max: 3.5rem (56px) */
font-size: clamp(2rem, 5vw, 3.5rem);
line-height: 1.15;
letter-spacing: -0.03em;
}
Interactive Playground: Fluid & Variable Typographyβ
Experiment with responsive typography scale, line-height ratios, and letter-spacing adjustments live:
Typographic Best Practices Checklistβ
| Objective | Recommended Technique | Anti-Pattern |
|---|---|---|
| Line Length (Measure) | Keep copy between 45β75 characters per line (max-width: 65ch). | Ultra-wide paragraphs stretching full screen width. |
| Line Height | Body copy: 1.5β1.6; Headings: 1.1β1.3. | Using px for line-height causing text overlapping when resized. |
| Color Contrast | Maintain at least 4.5:1 WCAG contrast ratio for normal text. | Low contrast light grey text on white backgrounds (#999999). |
| Performance | Load woff2 formats; set font-display: swap. | Loading .ttf or .otf files without fallback strategies. |