Learn CSS in 10 DaysDay 4: Typography
Chapter 4Learn CSS in 10 Days

Day 4: Typography

What You'll Learn Today

  • Font families and font stacks
  • Font sizes and the right units to use
  • Line height, letter spacing, and word spacing
  • Web fonts with Google Fonts
  • Text decoration and styling
  • Managing fonts with CSS variables

Font Families

body {
    font-family: "Helvetica Neue", Arial, sans-serif;
}

This is called a font stack. The browser tries each font from left to right, falling back to the next if a font is unavailable.

Generic Font Families

Keyword Style Examples
serif Has decorative strokes Times New Roman, Georgia
sans-serif Clean, no strokes Arial, Helvetica
monospace Fixed-width characters Courier New, Consolas
cursive Script-like Comic Sans MS
system-ui OS default font San Francisco, Segoe UI
/* Modern font stack */
body {
    font-family: system-ui, -apple-system, "Segoe UI", Roboto,
                 "Helvetica Neue", Arial, sans-serif;
}

/* Code font stack */
code {
    font-family: "Fira Code", "Source Code Pro", Consolas, monospace;
}

Tip: Using system-ui automatically applies each operating system's native font, giving your site a natural feel on every platform.


Font Sizes

h1 { font-size: 2.5rem; }    /* 40px (assuming 16px root) */
h2 { font-size: 2rem; }      /* 32px */
h3 { font-size: 1.5rem; }    /* 24px */
body { font-size: 1rem; }    /* 16px (browser default) */
small { font-size: 0.875rem; } /* 14px */

rem vs em

flowchart LR
    subgraph Units["Font Size Units"]
        REM["rem<br>Relative to root element<br>Predictable"]
        EM["em<br>Relative to parent<br>Compounds when nested"]
    end
    style REM fill:#22c55e,color:#fff
    style EM fill:#f59e0b,color:#fff
Unit Reference Best For
rem Root element's font-size Font sizes across the board
em Parent element's font-size Relative padding/margin
px Fixed pixel value Borders and other fixed sizes

Best practice: Use rem for font sizes. This ensures your layout scales properly when users change their browser's default font size.


Font Weight and Style

.light   { font-weight: 300; }
.normal  { font-weight: 400; }   /* same as "normal" */
.medium  { font-weight: 500; }
.bold    { font-weight: 700; }   /* same as "bold" */
.heavy   { font-weight: 900; }

.italic  { font-style: italic; }
.oblique { font-style: oblique; }

Line Height

body {
    line-height: 1.6;   /* 1.6 times the font size */
}

h1 {
    line-height: 1.2;   /* tighter for headings */
}

Guidelines: Body text reads best at 1.5 to 1.8. Headings look better at 1.1 to 1.3. Use unitless values so the line height scales proportionally with the font size.


Letter Spacing and Word Spacing

.spaced {
    letter-spacing: 0.05em;    /* widen space between characters */
}

.heading {
    letter-spacing: -0.02em;   /* tighten large text */
}

.loose {
    word-spacing: 0.1em;       /* widen space between words */
}

Text Alignment and Decoration

.center  { text-align: center; }
.right   { text-align: right; }
.justify { text-align: justify; }

/* Text decoration */
.underline    { text-decoration: underline; }
.line-through { text-decoration: line-through; }
.no-underline { text-decoration: none; }

/* Custom underline */
.fancy-underline {
    text-decoration: underline wavy #3b82f6;
    text-underline-offset: 4px;
}

/* Text transform */
.uppercase  { text-transform: uppercase; }
.lowercase  { text-transform: lowercase; }
.capitalize { text-transform: capitalize; }

Text Truncation

/* Single-line truncation */
.truncate {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Multi-line truncation */
.line-clamp {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

Google Fonts

1. Choose a Font

Visit fonts.google.com and pick your fonts.

2. Add the Link Tags

<head>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
</head>

3. Use in CSS

body {
    font-family: "Inter", sans-serif;
}
flowchart LR
    subgraph WebFont["Using Google Fonts"]
        Select["1. Choose fonts<br>fonts.google.com"]
        Load["2. Add link tags<br>in the HTML head"]
        Use["3. Apply in CSS<br>font-family"]
    end
    Select --> Load --> Use
    style Select fill:#3b82f6,color:#fff
    style Load fill:#22c55e,color:#fff
    style Use fill:#f59e0b,color:#fff

Performance: Adding display=swap tells the browser to show a system font while the web font loads, then swap it in once ready. This prevents invisible text during loading.


Managing Fonts with CSS Variables

:root {
    --font-sans: "Inter", system-ui, sans-serif;
    --font-mono: "Fira Code", "Source Code Pro", monospace;

    --text-xs: 0.75rem;
    --text-sm: 0.875rem;
    --text-base: 1rem;
    --text-lg: 1.125rem;
    --text-xl: 1.25rem;
    --text-2xl: 1.5rem;
    --text-3xl: 2rem;
}

body {
    font-family: var(--font-sans);
    font-size: var(--text-base);
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
code { font-family: var(--font-mono); }

Practice: Blog Article Typography

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: "Inter", system-ui, sans-serif;
    font-size: 1rem;
    line-height: 1.6;
    color: #1e293b;
    max-width: 680px;
    margin: 0 auto;
    padding: 48px 16px;
}

h1 {
    font-size: 2.5rem;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.02em;
    margin-bottom: 16px;
}

.subtitle {
    font-size: 1.25rem;
    color: #64748b;
    margin-bottom: 32px;
}

h2 {
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.3;
    margin-top: 48px;
    margin-bottom: 16px;
}

p {
    margin-bottom: 24px;
}

blockquote {
    border-left: 4px solid #3b82f6;
    padding-left: 24px;
    margin: 32px 0;
    font-style: italic;
    color: #475569;
}

code {
    font-family: "Fira Code", monospace;
    background: #f1f5f9;
    padding: 2px 6px;
    border-radius: 4px;
    font-size: 0.875em;
}

.meta {
    font-size: 0.875rem;
    color: #94a3b8;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

Summary

Concept Description
font-family Font stack with fallbacks
rem Root-relative sizing unit
line-height Line spacing (unitless recommended)
letter-spacing Space between characters
Google Fonts Load web fonts via <link>
CSS variables Centralize font configuration

Key Takeaways

  1. Use rem for font sizes
  2. Set body line height to 1.5 -- 1.8, headings to 1.1 -- 1.3
  3. Always provide a font stack with multiple fallbacks
  4. Use display=swap with Google Fonts for optimal loading performance

Exercises

Exercise 1: Basics

Pick a font from Google Fonts and apply different fonts to headings and body text.

Exercise 2: Applied

Create a type scale system using CSS variables (xs, sm, base, lg, xl, 2xl, 3xl) and apply it across your page.

Challenge

Style an entire blog article with appropriate typography for headings, body text, blockquotes, inline code, and metadata. Every text element should feel intentional.


References


Next up: On Day 5, we explore Colors and Backgrounds β€” gradients, background images, transparency, and shadows to bring your designs to life.