← Back to Articles

Advanced CSS: Typography & Fonts

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

Next Steps