Typography Basics — font-family, font-size, font-weight, font-style
Typography has a greater impact on how professional a website feels than most beginners expect. The same content set in a well-chosen font at a readable size feels completely different from the browser’s default Times New Roman at 16px. This lesson covers the four foundational CSS typography properties.
font-family
Section titled “font-family”font-family sets the typeface for an element and its descendants. CSS uses a font stack — a comma-separated list of fonts in priority order:
body { font-family: 'Inter', system-ui, -apple-system, sans-serif;}The browser tries fonts from left to right and uses the first one that is available. The last value should always be a generic family as the final fallback:
| Generic family | Appearance |
|---|---|
serif | Has decorative strokes (Times New Roman, Georgia) |
sans-serif | No decorative strokes (Arial, Helvetica, system-ui) |
monospace | Fixed-width characters (Courier, Consolas) |
cursive | Handwriting style (rarely used in body text) |
Font names with spaces must be quoted: 'Open Sans'. Single-word names do not require quotes: Georgia.
System font stack — loads the operating system’s default UI font, which is always available and fast:
body { font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;}This gives macOS users SF Pro, Windows users Segoe UI, and Android users Roboto — all at zero load cost.
font-size
Section titled “font-size”font-size sets the size of the text. Three units are most relevant for web typography:
px — absolute pixels. Predictable, but does not scale when the user changes their browser’s base font size.
h1 { font-size: 36px; }em — relative to the element’s parent font size. 1em equals the parent’s font size. If the parent is 20px, then 1.5em = 30px.
.tour-card p { font-size: 0.875em; /* 87.5% of the parent's font size */}em can compound unexpectedly when nested — a child’s 1.5em inside a parent’s 1.5em becomes 1.5 × 1.5 = 2.25 times the root size.
rem — relative to the root (<html>) font size, not the parent. By default, 1rem = 16px. This is the recommended unit for most font sizes because it scales predictably and respects user browser preferences.
h1 { font-size: 2.25rem; } /* 36px at default root size */h2 { font-size: 1.75rem; } /* 28px */h3 { font-size: 1.25rem; } /* 20px */p { font-size: 1rem; } /* 16px — the base */Why rem for accessibility: users who need larger text can increase their browser’s default font size (e.g., from 16px to 20px). Elements sized in rem will scale accordingly. Elements sized in px will not.
font-weight
Section titled “font-weight”font-weight controls how thick or thin the font strokes are. You can use keyword values or numeric values:
/* Keywords */p { font-weight: normal; } /* 400 */strong { font-weight: bold; } /* 700 */
/* Numeric — 100 to 900 in steps of 100 */h1 { font-weight: 700; }.light-label { font-weight: 300; }.black-heading { font-weight: 900; }Not all fonts support all weight values. If a font only has regular (400) and bold (700), the browser will use the nearest available weight for any other value you request.
font-style
Section titled “font-style”font-style controls whether the text is upright or angled:
em, cite, blockquote { font-style: italic; }.tour-tagline { font-style: italic; }.reset-italic { font-style: normal; } /* removes italic from nested elements */| Value | Result |
|---|---|
normal | Upright text (default) |
italic | Uses the italic version of the font |
oblique | Algorithmically slants the upright font when no italic version exists |
In most cases, italic is what you want. oblique is a fallback mechanism and rarely produces attractive results — if the font has an italic variant, italic will use it.
The font shorthand
Section titled “The font shorthand”All four properties (plus line-height) can be set in one font declaration:
/* font: style weight size/line-height family */h1 { font: italic 700 2.25rem/1.2 'Playfair Display', serif;}The size/line-height pair is required — you cannot use font shorthand without specifying both. The order is strict: style, then weight, then size/line-height, then family.
In practice, most developers write the properties individually for clarity. The shorthand is mostly encountered when reading others’ code.
Inheritance
Section titled “Inheritance”Font properties inherit from parent to child automatically. Setting font-family and font-size on body applies them to every element on the page:
body { font-family: 'Inter', system-ui, sans-serif; font-size: 1rem; font-weight: 400;}Every <p>, <span>, <li>, and heading on the page will use Inter by default — unless you override them with a more specific rule.
Exercise
Section titled “Exercise”Build the STO typography base:
- Set the body font and size:
body { font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 1rem; font-weight: 400; line-height: 1.6; color: #1a1a1a;}- Create a heading type scale using
rem:
h1 { font-size: 2.5rem; font-weight: 700; }h2 { font-size: 1.875rem; font-weight: 700; }h3 { font-size: 1.25rem; font-weight: 600; }- Style pull quotes or tour taglines with italic:
.tour-tagline { font-style: italic; font-size: 1.1rem; color: #3a5c26;}- Open the browser. The page text should be noticeably more readable than browser defaults. Compare your headings —
h1should be clearly larger thanh2, which should be larger thanh3.
font-familysets a font stack — the browser tries fonts left to right and uses the first available; always end with a generic family.- Use
remfor font sizes to respect user browser preferences and prevent compounding issues. font-weight: 400= normal,700= bold; numeric values 100–900 give finer control.font-style: italicuses the font’s italic variant;normalresets to upright.- Font properties inherit — set them on
bodyand they flow to all descendants.
Lesson 04 covers the remaining text properties: line-height, letter-spacing, text-align, text-decoration, and text-transform.