← Back to Articles
Font Families
/* Font stack with fallbacks */
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, sans-serif;
}
/* Monospace stack */
code {
font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;
}
/* Serif stack */
h1 {
font-family: Georgia, 'Times New Roman', serif;
}
@font-face
/* Self-hosted font */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2'),
url('/fonts/custom.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
/* Multiple weights */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom-bold.woff2') format('woff2');
font-weight: 700;
font-display: swap;
}
font-display
/* auto - Browser default */
/* block - Hide text briefly, then swap */
/* swap - Show fallback, then swap */
/* fallback - Hide briefly, then fallback if slow */
/* optional - Use fallback if font not ready */
@font-face {
font-family: 'MyFont';
src: url('font.woff2') format('woff2');
font-display: swap; /* Best for performance */
}
/* optional for icon fonts */
@font-face {
font-family: 'Icons';
src: url('icons.woff2') format('woff2');
font-display: optional;
}
Variable Fonts
/* Single file, multiple weights */
@font-face {
font-family: 'VariableFont';
src: url('font-variable.woff2') format('woff2-variations');
font-weight: 100 900;
font-stretch: 75% 125%;
}
/* Use variable axes */
.text {
font-variation-settings:
'wght' 450,
'wdth' 100,
'slnt' -5;
}
/* Animate weight */
.button:hover {
font-variation-settings: 'wght' 700;
transition: font-variation-settings 0.3s;
}
Typography Scale
:root {
--scale-ratio: 1.25; /* Major third */
--font-base: 1rem;
--font-xs: calc(var(--font-base) / var(--scale-ratio));
--font-sm: var(--font-base);
--font-md: calc(var(--font-base) * var(--scale-ratio));
--font-lg: calc(var(--font-md) * var(--scale-ratio));
--font-xl: calc(var(--font-lg) * var(--scale-ratio));
--font-2xl: calc(var(--font-xl) * var(--scale-ratio));
}
h1 { font-size: var(--font-2xl); }
h2 { font-size: var(--font-xl); }
h3 { font-size: var(--font-lg); }
p { font-size: var(--font-sm); }
Line Height & Rhythm
:root {
--line-height-tight: 1.25;
--line-height-base: 1.5;
--line-height-relaxed: 1.75;
}
h1, h2 { line-height: var(--line-height-tight); }
p { line-height: var(--line-height-base); }
.prose { line-height: var(--line-height-relaxed); }
/* Vertical rhythm */
* { margin-top: 0; margin-bottom: 1.5rem; }
h1, h2, h3 { margin-top: 2rem; }
Responsive Typography
/* Fluid typography with clamp */
h1 {
font-size: clamp(1.5rem, 5vw, 3rem);
}
/* Media query approach */
body { font-size: 16px; }
@media (min-width: 768px) { body { font-size: 18px; } }
@media (min-width: 1024px) { body { font-size: 20px; } }
/* Responsive line-height */
p {
line-height: clamp(1.5, 2vw, 1.8);
}
Icon Fonts vs SVG
/* Icon font */
@font-face {
font-family: 'Icons';
src: url('icons.woff2') format('woff2');
}
.icon::before {
font-family: 'Icons';
content: '\e001';
}
/* SVG icon (recommended) */
/* SVG advantages:
- Crisper rendering
- Individual color control
- Better accessibility
- No FOIT issues
*/
Key Takeaways
- Use font stacks with fallbacks
- Prefer font-display: swap for performance
- Consider variable fonts for flexibility
- Establish a typography scale
- Use clamp() for responsive type