Master typeface anatomy, type classification systems, and the core principles that drive effective web typography. Build the vocabulary every developer needs to collaborate fluently with designers.
Before you can choose or implement a typeface effectively, you need to speak its language. Typeface anatomy gives you precise vocabulary — baseline, x-height, counter, bowl — that makes design conversations productive. Classification tells you why a humanist sans feels warmer than a grotesque, and why a transitional serif works in editorial contexts where a slab serif would feel heavy. This lesson grounds you in the terminology and mental models that drive every good typographic decision.
Every letterform is built from named parts that directly affect readability on screen. The baseline is the invisible line letters sit on; inconsistent baseline alignment in mixed-font compositions causes visual tension. The x-height — the height of lowercase letters relative to capitals — is the single biggest factor in perceived size: a typeface with a tall x-height (like Inter) reads larger at the same font-size than one with a small x-height (like Garamond). Ascenders reach above the x-height (b, d, h, k, l), descenders drop below the baseline (g, p, q, y). The counter is the enclosed or partially enclosed white space inside letters like 'o', 'e', and 'c' — small counters close up at small sizes, hurting legibility. The stem is a straight vertical or diagonal stroke; the bowl is a curved stroke enclosing a counter. When you see a typeface described as having 'open apertures', it means the counters are generously open, which improves legibility in body text. Knowing these terms lets you articulate why 'this font breaks at 12px' (closed counters) rather than just 'it looks bad'.
Type classification isn't academic trivia — it's a decision framework. Serif typefaces have finishing strokes (serifs) at stroke terminals. Old Style serifs (Garamond, Palatino) have diagonal stress and low contrast; Transitional serifs (Times New Roman, Georgia) have vertical stress and higher contrast; Modern/Didone serifs (Bodoni, Didot) have extreme thick-thin contrast — beautiful in large display sizes, illegible in body text. Sans-serif typefaces omit serifs entirely. Humanist sans (Gill Sans, Frutiger, Calibri) have organic, calligraphic proportions — warm and readable. Grotesque sans (Helvetica, Akzidenz-Grotesk) are neutral and functional. Geometric sans (Futura, Avenir, Nunito) use strict geometric shapes — distinctive but can tire the eye in long text. Monospace typefaces (Courier, Fira Code, JetBrains Mono) give every character equal width — essential for code. Display typefaces are designed only for large sizes: headings, logos, posters. They often sacrifice legibility at small sizes for personality at large ones. For body text on the web, reach for Humanist sans or Transitional serifs with tall x-heights and open counters.
Screens render at 72-144 PPI in typical viewing; fine details that print beautifully at 300+ DPI disappear or turn to noise on screen. This is why hairline serifs on Didone typefaces look elegant in print but pixelate or disappear on screen. Optical size axes in variable fonts (opsz) let you use the same font file but adjust letterforms for display vs. body use. Weight matters enormously: at 400 (Regular), body text is readable; at 300 (Light), contrast against a white background drops and WCAG 1.4.3 compliance requires larger point sizes to maintain a 4.5:1 contrast ratio. Avoid 'faux bold' — when the browser synthesises bold by adding stroke width to a non-bold font. Always load the actual bold weight file and declare it with font-weight: 700 in the @font-face block. CSS font-weight values: 100=Thin, 200=ExtraLight, 300=Light, 400=Regular, 500=Medium, 600=SemiBold, 700=Bold, 800=ExtraBold, 900=Black. Map these to the actual weights your typeface provides — if your font only has 400 and 700, don't declare 300 or the browser will fake it.
The font-family property accepts a comma-separated fallback list. Always end with a generic family keyword. Generic families — serif, sans-serif, monospace, cursive, system-ui — are guaranteed to resolve. The font-style property maps to italic or oblique faces. Never set font-style: italic without loading an actual italic font file; the browser will synthesise a slanted version of the upright face, which looks crude. The font-variant shorthand controls OpenType features including small-caps. Here is a correct, minimal font stack declaration:
1/* Correct @font-face with actual weights loaded */
2@font-face {
3 font-family: 'Inter';
4 src: url('/fonts/inter-regular.woff2') format('woff2');
5 font-weight: 400;
6 font-style: normal;
7 font-display: swap;
8}
9
10@font-face {
11 font-family: 'Inter';
12 src: url('/fonts/inter-bold.woff2') format('woff2');
13 font-weight: 700;
14 font-style: normal;
15 font-display: swap;
16}
17
18/* Fallback stack ordered from specific to generic */
19body {
20 font-family: 'Inter', -apple-system, BlinkMacSystemFont,
21 'Segoe UI', Helvetica, Arial, sans-serif;
22 font-weight: 400; /* Explicitly set — never rely on browser default */
23 font-size: 1rem; /* 16px base */
24}
25
26h1, h2, h3 {
27 font-weight: 700; /* Maps to loaded bold file, not faux bold */
28}The fallback list after 'Inter' provides a visual bridge: -apple-system and BlinkMacSystemFont pick up San Francisco on macOS/iOS, Segoe UI on Windows, and Helvetica/Arial as final fallbacks before the generic sans-serif. This minimises layout shift if the custom font is slow to load.
Start with use-case: body text demands high legibility (open counters, moderate contrast, tall x-height, extensive Latin character coverage). Display text can prioritise personality over legibility. UI text (labels, tooltips, inputs) needs consistency at small sizes and good hinting. Then filter by classification: neutral interfaces lean toward Humanist or Grotesque sans; editorial content can use Transitional serifs; technical documentation usually wants Humanist sans or Geometric sans for clarity. Verify: Does it include all the weights you need (no faux bold risks)? Does it cover the character sets for your audience (accents, Greek, Cyrillic)? Is it available under a license compatible with your project (SIL Open Font License = free, OFL; proprietary = licensing fee)? Finally, test at actual rendering sizes in a real browser at 96 DPI — not Figma, not a screenshot. A typeface that looks perfect at 2x in Figma may appear soft or blurry at 1x on a standard monitor.
1/* Quick legibility test: check x-height ratio visually */
2.legibility-test {
3 font-family: 'YourFont', sans-serif;
4 font-size: 14px; /* Small UI size */
5 line-height: 1.5;
6 /* Look at: o vs O height ratio (x-height),
7 il1 distinction, rn vs m distinction */
8}
9
10/* Check these character pairs for legibility: */
11/* I l 1 | O 0 | rn m | a o | f t */Load Inter and Garamond side-by-side at the same font-size and compare x-height, counter openness, and stroke contrast. Then deliberately trigger faux bold by omitting the bold @font-face declaration and observe the difference.
In the next lesson, you'll learn how font-display, preload hints, and FOUT/FOIT strategies control the loading experience — ensuring your carefully chosen typeface appears quickly without layout shift or invisible text.
Your progress is saved in this browser, on this device only.