Typography. Most of your interface is words.

Strip the colour, icons and illustrations from almost any app and what is left is text: labels, numbers, messages, headings, paragraphs. This guide teaches you to set that text so it reads effortlessly, from the anatomy of a letter to the line length of a paragraph to the apostrophe in “don’t”. It is the deepest single-subject guide in the course, because type is the one material you will touch in every screen you ever ship.

Reading timeAbout 4 hours, in 5 sittings
Practice time2 weeks
Before thisVisual Design
TeachersReichenstein, Bringhurst, Butterick, Spiekermann, Frere-Jones, Carter, Warde

By the end you will be able to

  • Name the parts of a letter and explain why x-height, aperture and spacing decide how a face behaves at screen sizes (understand)
  • Classify a typeface by its structure and predict where it will work and where it will fail (analyse)
  • Choose a type system for a product: system or custom, which families, how many, and with what licence (evaluate)
  • Set body text with the right size, leading and measure, and build a type scale of five to seven sizes (create)
  • Fix the details that separate amateur from professional text: quotes, dashes, figures, tracking, wrapping and truncation (apply)
  • Make type survive real conditions: user font sizes, Windows rendering, slow font loading, dark mode and Indian scripts (create)

Warm-up: what do you already see?

Before any theory, test your eye. These three questions are a diagnostic, not a grade. If you get them all right, you already notice type; this guide will give you the vocabulary and the numbers behind that instinct. If you miss them, good: you now know exactly what to watch for as you read.

How to study this guide: read one Part per sitting. Do each chapter’s quiz before you move on, and do at least the exercises marked “on your own product”. Keep your own app open in another window the whole time. Typography is learned with the eyes and hands, so every time you read a rule, look for it in your screen and change one thing.

A

Your subscription renews on the first of each month. If you cancel before then, you will keep access until the end of the current period and you will not be charged again. Receipts are emailed to the address on your account and are also available under Settings, Billing, History.

Version A
B

Your subscription renews on the first of each month. If you cancel before then, you keep access until the end of the current period and won’t be charged again. Receipts are emailed to you and live in Settings › Billing.

Version B
Diagnostic 1

Version B above feels easier to read. Which change contributes the most?

Diagnostic 2

A dashboard shows a column of prices: ₹1,111.00 above ₹9,990.00. The digits don’t line up vertically even though the column is right-aligned. What is wrong?

Diagnostic 3

Which of these strings is typographically correct for an English UI?

Part one

Seeing type

Before you can choose or set type well, you need to see it: the parts of a letter, the families typefaces belong to, and what actually happens in a reader’s eyes. These four chapters build the vocabulary every later decision uses.

1

Why type is most of the interface

Taught by Oliver Reichenstein, with Beatrice Warde and Robert Bringhurst

In software, typography is not decoration on top of the design; for most screens it is the design, so getting type right improves every screen at once.

In 2006 Oliver Reichenstein of Information Architects published an essay called “Web Design is 95% Typography”. His argument was simple: the overwhelming majority of what people consume on the web is written language, so the core skill of a web designer should be shaping written information. Twenty years on, the claim holds for products too. Look at a to-do app, a banking app, a settings screen or a code editor and count the pixels that are text versus everything else. Text is the interface.

This has a practical consequence for you as a solo creator. Type decisions are the highest-leverage design decisions you can make, because they are global. Change the body size, leading and colour once in your CSS or your SwiftUI text styles, and every screen improves. Polish one illustration and one screen improves. If you have limited time (you do), type is where to spend it first.

A screen as drawn The same screen, text only Settings AccountRohit NotificationsOn AppearanceSystem Storage2.4 GB Version 1.4.2 · Sync on Settings AccountRohit NotificationsOn AppearanceSystem Storage2.4 GB Version 1.4.2 · Sync on
Delete everything but the words and the screen still works. Delete the words and nothing works. Hierarchy, grouping and meaning in most product screens are carried by type: size, weight, colour, position.

The crystal goblet

In a 1930 lecture later published as “The Crystal Goblet”, the typographer Beatrice Warde compared good typography to a clear glass: a wine lover wants a goblet that reveals the wine, not an ornate gold cup that hides it. Her point was that type in the service of reading should be invisible. The reader should notice the meaning, not the letters.

That idea is the north star for product typography, with one adjustment. In a product, type has two jobs. In reading mode (an article, a note, a long description) it should disappear. In interface mode (labels, buttons, numbers, headings) it should be instantly scannable, which means it must create clear differences: this is a heading, that is a label, this number matters more than that one. Good product typography is invisible in the first job and quietly structured in the second.

Typography exists to honor content.Robert Bringhurst, The Elements of Typographic Style

What “good” looks like on a screen

Bringhurst wrote for books, Matthew Butterick (Practical Typography) translated much of it for the web, and both agree on the goal: text that respects the reader’s time and attention. On a screen that comes down to five testable qualities, which the rest of this guide unpacks one by one:

  1. Comfortable body text. Big enough, with enough line spacing, at a line length the eye can track (Chapter 7).
  2. Clear hierarchy with few means. A small set of sizes and weights, each with a job (Chapters 8 and 9).
  3. Consistent rhythm. Spacing that follows a system, so related things sit together (Chapter 10).
  4. Correct details. Real quotes, proper dashes, aligned figures (Chapters 12 to 14).
  5. Robustness. Text that survives long names, large user font sizes, slow networks, Windows rendering and other scripts (Part five).
Don't
Weekly Report! YOUR STATS ARE IN Tasks completed: 42 Streak: 7 days Keep going, you are doing great VIEW DETAILS
Every line shouts in a different voice. Five families, no order. The eye has nowhere to start.
Do
THIS WEEK 42 tasks done 7-day streak, your longest yet. View details ›
One family, two weights, three sizes. The number leads, the label explains, the action waits.
Key idea

Type is the one design decision that touches every screen. Fix it globally first, and decorate later, if ever.

For the solo creator

You likely design in code. That is an advantage: your type system can live in a dozen lines of CSS custom properties or a single Swift file of text styles, and every component inherits it. Spend your first design hour of any project on those dozen lines. They will outlive most of your other decisions.

Do

  • Treat type settings as global tokens you set once and reuse.
  • Judge a screen by squinting: can you still see the order?
  • Let content decide: read the real text before styling it.

Don't

  • Use type to decorate when it should inform.
  • Set sizes ad hoc per component (“this one looks better at 15px”).
  • Design with lorem ipsum; real words have real lengths and rhythms.

In the wild

  • iA WriterInformation Architects, 2010
    Almost no chrome: the product is a single, carefully set column of text in a custom typeface derived from IBM Plex Mono. Users pay for how the text feels. When type is right, it can be the whole product.
  • Things 3Cultured Code, 2017
    Uses Apple’s system font and builds its calm look almost entirely from size, weight, grey values and generous spacing. You don’t need a custom font to look crafted; you need a disciplined system.
  • KindleAmazon, 2007 to today
    Amazon commissioned Bookerly (Dalton Maag, 2015) specifically for reading on its screens, and gives readers control of size, margins and line spacing. For a reading product, typography is the core feature, not a skin.

Common mistakes

Polishing visuals while body text is 13px grey on white

Illustrations and gradients are fun and visible in screenshots; body text feels boring.

Audit body text first: size, contrast, leading, measure. It is the bulk of what users look at.

Type decided component by component

Each screen is built in isolation, so each gets “whatever looked fine”.

Define named text styles (body, small, label, title, heading, display) before building screens, and refuse new ones without a reason.

Check yourself

You have one free afternoon to improve the look of your note-taking app. Which change will be noticed on the most screens?

Exercise 1.1 30 minutes · on your own product

The text-only screenshot

  1. Take screenshots of three key screens of your product.
  2. In any editor, cover every non-text element (icons, images, colour fills) with a flat grey box.
  3. For each screen, write one sentence: can a stranger still tell what is most important, what is secondary and what is clickable?
  4. List the type-only fixes that would restore any lost order (size, weight, colour, spacing).
You're done when: you have three masked screenshots and a list of at least five type fixes, ranked by how many screens each would touch.
BeginnerCompetentStrong
Masked screens, vague notes (“looks messy”).Specific fixes per screen (“title and label are both 15px semibold”).Fixes expressed as global rules (“one title size; labels always muted 13px”), ranked by reach.
2

The anatomy of type

Taught by Erik Spiekermann, with Matthew Carter and Tobias Frere-Jones

A few measurable parts of a letter (x-height, aperture, contrast, spacing) predict almost everything about how a typeface will behave at screen sizes.

You don’t need to draw type to design with it, but you do need to see it. Spiekermann’s Stop Stealing Sheep & Find Out How Type Works exists because most people look at letters and see only “nice” or “not nice”. Designers see parts. Once you can name the parts, you can predict behaviour: this face will blur at 12px, that one will look huge at 16px, this one will turn grey and weak in dark mode.

Hxgpa ascender line cap height x-height baseline descender line x-height Guides are approximate for Source Serif; every face sets them a little differently, and those differences are the point. Parts: stem (H’s uprights) · serif (feet) · bowl, counter (p, a) · terminal (top of a) · descender (g, p) · aperture.
The five horizontal guides. Cap height and x-height are the two that matter most on screens. The ratio between them is where the “size” of a typeface really lives.
Baseline
The invisible line letters sit on. Round letters (o, e) dip slightly below it (overshoot) so they look aligned with flat ones.
x-height
The height of lowercase letters without ascenders, like x, a, e. Because most reading happens in lowercase, x-height determines how big a face looks. Two faces at 16px can differ by 15% or more in apparent size.
Cap height
The height of flat capitals like H. Cap height matters for aligning text to icons and for all-caps labels.
Ascender and descender
The parts of b, d, h, k, l that rise above the x-height, and of g, j, p, q, y that drop below the baseline. Long extenders help word recognition but need more line spacing.
Stem
The main vertical stroke, like the uprights of H or the spine of l. Stem thickness defines weight.
Bowl and counter
The bowl is the curved stroke enclosing a space (in b, d, o, p). The counter is the enclosed or partly enclosed space itself. Small counters fill in with ink, or with blur on low-resolution screens.
Aperture
How open a partly enclosed counter is, in c, e, a, s. Open apertures keep letters distinct at small sizes.
Terminal
The end of a stroke that has no serif, like the top of a or the end of c. It can be ball-shaped, sheared, flat or tapered.
Serif
The small foot or cap at the end of a stroke. Sans serif means without.
Contrast
The difference between thick and thin strokes. High contrast looks elegant in print and large sizes; at small screen sizes the thin strokes can vanish.
Sidebearings and spacing
The built-in space on each side of a glyph. Spacing is as much part of the design as the shapes; loose spacing reads better small, tight spacing looks better large.

Why x-height matters on screens

Screens are lower resolution than print. A 16px letter on a typical display has its x-height drawn with roughly 7 to 9 pixels. Every pixel of x-height you gain makes counters bigger and shapes more distinct. That is why faces designed for screens, such as Verdana and Georgia (Matthew Carter, 1996, made for Microsoft when screens were coarse), have large x-heights and generous spacing. It is also why a classical book face like Garamond looks small and spindly at the same nominal size: its x-height is modest and its strokes are thin.

Same font-size (40px), different apparent size Handgloves EB Garamond: small x-height Handgloves Literata: screen-tuned serif Handgloves Atkinson Hyperlegible: large x-height
The px value is not the size you see. When you swap fonts, re-tune the size by eye. A face with a small x-height may need 18–20px to read like another face at 16px.

Why aperture matters

Aperture is the most underrated screen-legibility feature. In a closed-aperture face (Helvetica is the classic example), the ends of c, e, a and s curl back towards each other. That looks tidy and uniform at large sizes. At small sizes, or with blur, motion or low vision, those letters start to look like o. Humanist sans serifs (Frutiger, Source Sans, Fira) keep the apertures open, so each letter stays itself.

Closed aperture Open aperture small gap: reads as o wide gap: stays c and e At 11px, on a blurry screen, closed c and e drift towards o. Open ones stay c and e.
Schematic, not a real typeface. Look at a, c, e, s in any font you are considering. If the strokes nearly touch, test it hard at your smallest UI size.

Contrast, terminals and other screen risks

High-contrast faces (Didot, Bodoni, Playfair Display) have hairline thin strokes. At 48px on a headline, gorgeous. At 14px on a Windows laptop, the hairlines fall below one pixel and break up. Low-contrast faces with sturdy strokes survive. Similarly, tiny distinctions like the difference between l (lowercase L), I (capital i) and 1 (one) are fine in a novel, where context resolves them, and dangerous in a password, a promo code or a file name. Atkinson Hyperlegible (Braille Institute, 2019) was designed specifically to exaggerate such distinctions for low-vision readers.

Don't

Il1 O0 rn m

Code: Il1lO0 (which is which?)

Ambiguous glyphs. Fine in prose, dangerous in codes, IDs and passwords.
Do

Il1 O0 rn m

Codes in IBM Plex Mono: Il1lO0

Distinct shapes. Use a face with a tailed l, serifed I and slashed or dotted zero wherever characters must be copied.
For the solo creator

Keep a one-line test string in your notes: Il1 O0 rn m a c e s 3 8 B. Paste it into any font you consider, at your smallest UI size, on the worst screen you own. Thirty seconds, and it catches most screen-legibility problems before you commit.

Do

  • Compare faces by x-height, not by nominal px.
  • Prefer open apertures and moderate contrast for UI and small text.
  • Check ambiguous glyphs wherever users copy characters.

Don't

  • Use hairline, high-contrast display faces below about 24px.
  • Assume 16px means the same size across fonts.
  • Judge a face from its marketing specimen at 72px.

In the wild

  • Verdana & GeorgiaMatthew Carter for Microsoft, 1996
    Designed for the coarse CRT screens of the 1990s, with large x-heights, wide spacing and shapes that hold up when drawn in few pixels. Screen faces are built around the pixel, not adapted to it.
  • RetinaFrere-Jones Type, for The Wall Street Journal
    A face for tiny financial tables, drawn with wide proportions and ink traps so numbers stay distinct at very small sizes. Small text needs a face designed for small text.
  • Atkinson HyperlegibleBraille Institute, 2019
    Exaggerated letterform differences (tailed l, slashed zero, distinctive b/d/p/q) for low-vision readers; free to use. Distinctness is a design parameter you can choose.

Common mistakes

Using a print book face for UI

It looked beautiful in a specimen at 60px.

Test at 12–16px on a non-Retina screen. Prefer faces with a screen heritage or explicit optical sizes for small text.

Swapping fonts without re-tuning size

The design tokens stay at 16px, but the new font has a 10% smaller x-height.

After any font swap, re-tune body size and line height by eye against the old version.

Ambiguous characters in codes

Recovery codes and licence keys are set in the UI font.

Use a monospace with distinct glyphs, or remove ambiguous characters from the alphabet you generate codes from.

Check yourself

Your app shows 2FA backup codes like “lO8Il1” to users who must type them on another device. People report codes “not working”. Best fix?

Exercise 2.1 40 minutes · on fonts you use daily

Anatomy field notes

  1. Pick three typefaces: your product’s UI font, the font of an app you love reading in, and one display face you admire.
  2. Type “Handgloves Il1 O0 aces” in each at 64px and at 13px.
  3. For each, note: x-height (small, medium, large relative to cap height), aperture (open or closed), contrast (low, medium, high), and anything that breaks at 13px.
  4. Write one sentence per face predicting where it belongs: body, UI labels, headings only, or nowhere in your product.
You're done when: you have a small table of three faces × four properties, and a usage prediction for each.
BeginnerCompetentStrong
Properties noted, but no link to usage.Each prediction follows from a property (“closed aperture, so not for 12px labels”).Predictions tested by setting a real screen at both sizes and confirmed or corrected.
3

Classification: families of form

Taught by Robert Bringhurst, with Erik Spiekermann

Typefaces fall into families defined by how their strokes were made; knowing a face’s family tells you its voice, its era and how it behaves on screen before you test it.

Classification is not trivia. Each category comes from a tool and a period: the broad-nib pen of Renaissance scribes, the engraver’s steel, the industrial sign painter, the geometric ideals of the Bauhaus. Those origins left fingerprints in the shapes (where the stress falls, how much contrast there is, how open the letters are), and those fingerprints are exactly what determine screen behaviour. Learn ten categories and you can read a new typeface the way a sommelier reads a label.

Rag Old style Pen-made, diagonal stress, low contrast Garamond, Bembo · 1500s Rag Transitional More vertical stress, sharper serifs Baskerville, Times · 1750s Rag Didone (modern) Vertical stress, hairline serifs, high contrast Bodoni, Didot · c. 1800 · here Playfair Rag Slab serif Heavy block serifs, low contrast Clarendon, Rockwell · 1800s posters Rag Grotesque Early sans, some quirks, slight contrast Franklin Gothic, Akzidenz · c. 1900 Rag Neo-grotesque Uniform, neutral, often closed apertures Helvetica, Univers · 1957 · here Inter Rag Humanist sans Pen-based proportions, open apertures Gill Sans, Frutiger · here Source Sans 3 Rag Geometric sans Circles and lines, single-storey a Futura (1927), Avenir · here Jost Rag Monospace Every glyph the same width Courier, SF Mono · here IBM Plex Mono RAG Display Built for big sizes only Posters, logos · here Bebas Neue
Ten families, ten fingerprints. Look at the “a” and “g”: two-storey and pen-shaped in old style, rounder and more uniform as you move to neo-grotesque and geometric. If fonts fail to load, your system substitutes similar faces.

The serif families

Old style faces come from the broad-nib pen, which makes thick and thin strokes depending on angle. The thinnest parts of an o sit on a diagonal (the “stress”). Contrast is modest, serifs are bracketed (they curve into the stem), and the whole thing feels warm and literary. They read well in long text, but classic old-style revivals often have small x-heights, so give them more size on screen.

Transitional faces (eighteenth century) straightened the stress towards vertical and sharpened the details. Times New Roman belongs here, and it was drawn for narrow newspaper columns, which is why it is compact.

Didones pushed contrast to the extreme: hairline serifs, vertical stress, ball terminals. Luxurious at magazine-cover sizes; fragile at text sizes on screens.

Slab serifs have thick, rectangular serifs and low contrast. Born for posters, they now include sturdy text faces (Roboto Slab, Zilla Slab) that hold up well on low-quality screens because nothing in them is thin.

The sans serif families

Grotesques were the first commercial sans serifs: slightly irregular, with some stroke contrast. Neo-grotesques (Helvetica, Univers) smoothed them into neutral, uniform shapes with horizontal terminals that curl in, which closes apertures. Humanist sans serifs bring back pen proportions and open apertures (Gill Sans, Frutiger, Myriad, Source Sans), and tend to be the most legible at small sizes. Geometric sans serifs build letters from circles and straight lines (Futura, Avenir, Jost); they are clean and stylish, but their perfectly round o, c, e and single-storey a can blur together in body text.

Most modern UI faces are hybrids. Inter is broadly neo-grotesque but with taller x-height and slightly more open forms tuned for screens. SF Pro sits between neo-grotesque and humanist. Don’t worry about precise labels; use the categories to predict behaviour.

CategoryVoiceGood on screen forRisks
Old styleLiterary, warm, bookishLong reading at 18px+Small x-height, thin details at 12–14px
TransitionalFormal, establishedArticles, editorial headingsTimes is narrow and dated as a UI default
DidoneFashion, luxuryBig headlines onlyHairlines vanish at small sizes and in dark mode
SlabSturdy, mechanical, friendlyHeadings, e-reader text, robust UICan feel heavy in dense UI
GrotesqueHonest, slightly grittyHeadings, editorial UIQuirks can distract in labels
Neo-grotesqueNeutral, modern, corporateUI, dashboardsClosed apertures at tiny sizes; can feel bland
Humanist sansFriendly, clearUI, small text, signage-like labelsLess “crisp” feeling than neo-grotesques
GeometricStylish, optimisticBrand, headings, short textRound letters blur in long text
MonospaceTechnical, typewriterCode, IDs, aligned data, writing toolsWide; uneven texture in prose
DisplayLoud, specificOne big wordUnreadable as text
Don't

Your order has shipped. Track the parcel from the Orders page, and contact us if anything looks wrong with the delivery address.

A Didone at 13px. Hairlines flicker and break; the paragraph looks grey and spotty.
Do

Your order has shipped. Track the parcel from the Orders page, and contact us if anything looks wrong with the delivery address.

A humanist sans at 15px. Even strokes, open shapes, calm texture. Save the Didone for a 40px heading if you need its voice.
Key idea

Origins predict behaviour: pen-made faces read warmly, engraved ones sparkle big and break small, geometric ones look great and read slower.

For the solo creator

You don’t need a library of fonts. Pick one sans that is good at small sizes (humanist or a screen-tuned neo-grotesque) and, only if your product involves long reading, one serif designed for screens. That covers 95% of products. Spend the saved hours on spacing.

Do

  • Choose by behaviour (size, aperture, contrast) first and voice second.
  • Use high-contrast and display faces only at large sizes.
  • Expect modern UI faces to be hybrids; test rather than label.

Don't

  • Pick a geometric sans for long body text because it looks modern.
  • Pair two faces from the same category (two neo-grotesques fight).
  • Use a display face for anything longer than a few words.

In the wild

  • Medium2012 onward
    Long-form posts are set in a serif at a generous size (around 20px) with a sans serif for UI and metadata. Serif for reading, sans for interface is a pattern because it works, not because it is a rule.
  • AirbnbCereal, 2018
    A custom geometric-leaning sans gives the brand a friendly, rounded voice across app and marketing. Geometric faces carry brand personality; product teams then tune size and spacing for legibility.
  • GitHubSystem fonts, 2017
    Switched its UI to the operating system’s font stack, with a monospace for code and later custom faces (Mona Sans, Hubot Sans) for marketing. Neutral UI, distinctive voice elsewhere.

Common mistakes

Choosing by mood board

The face fit the brand vibe in a 120px hero image.

Shortlist by voice, then eliminate by behaviour: set your real UI at 12, 14 and 16px and keep only what survives.

Monospace for everything

It feels “developer”, so it goes on buttons, headings and paragraphs.

Keep monospace for code, IDs and deliberate writing-tool contexts (see Chapter 18). Prose in monospace is wide and uneven.

Check yourself

You are building a calm reading app for long essays. Which pairing is most likely to work?

Exercise 3.1 30 minutes · on apps you use daily

Classify your home screen

  1. Open five apps you use daily. For each, identify the UI typeface (screenshots plus a font-identifier tool, or the browser inspector for web apps).
  2. Place each in a category from the table above.
  3. Note one place where the face’s family helps (or hurts) the product’s job.
You're done when: you have five rows: app, face, category, one observation about fit.
BeginnerCompetentStrong
Faces named, categories guessed.Categories justified by visible traits (stress, aperture, terminals).Observations link traits to the product’s job and suggest a better alternative where fit is poor.
4

Legibility, readability and how eyes read

Taught by Kevin Larson (reading research), with Walter Tracy and Keith Rayner

Reading is a series of quick jumps and short stops; typography helps when it makes each stop easy (legibility) and each jump predictable (readability).

Two words that people use interchangeably mean different things. In Walter Tracy’s classic distinction, legibility is about the typeface: how easily individual characters can be told apart. Readability is about the setting: how comfortably a block of text can be read for a long time, which depends on size, spacing, line length, contrast and layout. A highly legible face can be set unreadably (8px, justified, 140 characters wide), and a modest face set with care can read beautifully.

Readability (the setting) → Legibility (the face) → Good face, bad setting The most common product failure: Inter at 12px, 1.2 leading, 120 characters wide. Good face, good setting The goal. Invisible type, reading feels effortless. Poor face, bad setting Fails. Users skim or leave. Quirky face, good setting Surprisingly tolerable. Setting rescues more than face choice does.
Setting beats selection. Most products already use a legible face. What they get wrong is size, spacing and length, which is good news: those are free to fix.

What the eyes actually do

Your eyes do not glide along a line. They make rapid jumps called saccades and brief stops called fixations. Eye-movement research summarized by Keith Rayner gives typical figures for skilled readers of English: fixations last around a quarter of a second, saccades jump around seven to nine characters, and somewhere around 10–15% of saccades go backwards (regressions) to re-check something. During a fixation you only see detail in a small window, a few letters to the left and more (roughly 14–15 characters) to the right. At the end of each line comes the return sweep, a long jump back to the start of the next line, which is where readers most often lose their place.

Good typography makes each jump land on a word. The return sweep is where readers get lost. regression return sweep ● fixation (~250 ms) ⌒ saccade (~7–9 characters) Long lines lengthen the sweep; tight leading makes its target small. Both cause re-reading.
Reading is jumping. Measure (line length) and leading (line spacing) exist mainly to make the return sweep reliable, which is why they matter so much (Chapter 7).

The word-shape myth

For decades designers repeated that we read by recognizing the outline of whole words (the “bouma”), and that this is why lowercase reads faster than all caps. In 2004 Kevin Larson of Microsoft’s advanced reading team published a review, The Science of Word Recognition, arguing that the evidence points elsewhere: readers recognize the letters within a word in parallel and use that information to identify the word. All-caps text is slower mostly because we have far less practice reading it, and alternating-case text slows people down because it disrupts letter recognition, not just outline.

Why this matters for you: it means letter distinctness (Chapter 2) is what you are designing for. Don’t justify all-caps paragraphs by saying “outline doesn’t matter”, and don’t justify tiny lowercase by saying “people read shapes anyway”. Make letters clear, words well spaced, and lines easy to track.

The myth: we read outlines reading Outline boxes are shared by many words. The evidence: letters, in parallel r e a d i n g Distinct letters make words recognizable.
Design for letters. Clear, distinct letterforms and good spacing are what help readers, as reviewed by Larson (2004).
Myth

“Serif is more readable in print, sans serif on screens.” Studies comparing serif and sans for reading speed and comprehension have mostly found small or no reliable differences once size and spacing are matched. On today’s high-density screens the old pixel argument against serifs has largely gone. Choose by voice, x-height, contrast and setting, not by the serif/sans rule.

Familiarity is a feature

Readers read fastest what they read most. That is a quiet argument for conventional choices: sentence case over all caps, mixed case over small caps for long text, familiar letterforms over quirky ones (a single-storey a or a playful g may charm in a logo and slow down a paragraph). Novelty costs attention. Spend it where you want attention, never in body text.

Don't

Your trial ends in three days. Choose a plan to keep your projects, or export everything as Markdown from Settings.

All caps paragraph. Slower to read because it is unfamiliar, and it reads as shouting.
Do

Trial

Your trial ends in three days. Choose a plan to keep your projects, or export everything as Markdown from Settings.

Caps only for a short label. Sentence case for the message, tracked caps for a two-word tag (Chapter 14).
For the solo creator

You can’t run eye-tracking studies, and you don’t need to. Read your own long screens aloud at normal speed. Wherever you stumble, lose your place or re-read, mark it. Those are your regressions and failed return sweeps, and the fix is almost always size, leading or line length.

Do

  • Separate “is the face legible?” from “is the setting readable?”
  • Design for return sweeps: moderate line length, enough leading.
  • Prefer familiar letterforms and sentence case for anything longer than a label.

Don't

  • Repeat the word-shape theory as a design rule.
  • Argue serif versus sans while body text is 13px.
  • Set paragraphs in all caps or small caps.

In the wild

  • Microsoft ClearType researchLate 1990s to 2000s
    Microsoft’s reading research group studied how rendering and type affect reading on screens, work connected to ClearType rendering and the ClearType font collection that shipped with Windows Vista (Calibri, Cambria, Consolas and others). Screen reading is a solvable engineering problem, not just taste.
  • Apple Books & Kindle2010s–today
    Both let readers choose a font, size and line spacing, accepting that comfort varies by person and eyesight. For long reading, give control; your defaults are a starting point.
  • UK GOV.UKGovernment Digital Service
    Uses sentence case almost everywhere, short line lengths and plain sizes, with research behind the style guide. Familiar, unshowy setting serves the widest audience.

Common mistakes

Blaming the font

Text feels hard to read, so the font must be wrong.

Before swapping fonts, try +2px size, line-height 1.5 and a 65-character measure. Most “bad fonts” are bad settings.

Caps for emphasis in sentences

It feels like the strongest way to make something stand out.

Use weight (semibold) for emphasis in UI, italics in prose. Keep caps for very short labels.

Check yourself

Users of your docs site say long pages are tiring; they keep losing their place. Body is Inter 15px, line-height 1.3, column 1100px wide. What do you change first?

Connect the ideas · Part one recap

In The Human Mind you met limited attention. Which typographic choice best respects it in a busy settings screen?

Exercise 4.1 25 minutes · on your own product

The read-aloud audit

  1. Pick the longest piece of text in your product (help article, onboarding, a long note, a description).
  2. Read it aloud at a normal pace from the screen, finger off the trackpad.
  3. Mark every stumble: lost line, re-read, squint, skipped word.
  4. For each mark, decide: is it legibility (a letter or glyph problem) or readability (size, leading, measure, contrast, alignment)?
You're done when: you have a marked-up screenshot and a count of legibility versus readability problems, plus one setting change you will test.
BeginnerCompetentStrong
Stumbles marked.Each stumble classified correctly as legibility or readability.Proposed change tested and the read-aloud repeated with fewer stumbles.
Part two

Choosing type

With the vocabulary in place, you can make the first real decision: which typefaces your product uses, how many, and under what licence. For most solo products the right answer is smaller and cheaper than you expect.

5

Choosing typefaces for a product

Taught by Matthew Butterick, with Rasmus Andersson and Oliver Reichenstein

Start from the system font and only leave it for a reason you can name; when you do leave it, choose a face built for screens that covers every size, weight, figure style and script you need.

Every font choice is a trade between three things: fit (does it suit your product’s job and voice), function (does it behave at your sizes, with your numbers, in your languages), and cost (licence, file size, loading time, maintenance). Designers new to type over-weight fit. Experienced ones start with function and cost, and let fit choose between the survivors.

Option one: the system font

Each platform ships a superb UI family: SF Pro on Apple platforms (since 2015), Segoe UI on Windows (Segoe UI Variable on Windows 11), Roboto on Android (since 2011, redesigned in 2014). On the web you reach all of them with one CSS stack, and you pay nothing in download size.

font-family: system-ui, -apple-system, "Segoe UI", Roboto,
             "Noto Sans", "Helvetica Neue", Arial, sans-serif;

What you get for free is easy to underestimate. Apple’s SF switches between Text and Display designs (and, in recent versions, uses a variable optical-size axis) and adjusts tracking by size automatically. System fonts support the platform’s Dynamic Type or text scaling. They cover many scripts, they are hinted for each platform’s renderer, and they make your app feel native because they are what everything else on the device uses.

What you give up: distinctiveness (you look like everyone), and cross-platform consistency (your web app will have slightly different widths on Mac, Windows and Android, so layouts must flex). A known wrinkle: on some Windows language settings, system-ui can resolve to a font you didn’t expect, which is one reason some teams list named fonts instead.

Option two: a chosen family

Choose a specific family when you have a reason: long reading where a serif voice matters, a brand that needs a distinctive voice, tabular data that needs particular figure features, or the need for identical metrics across platforms. Then hold the face to a function checklist before you fall for it.

Native app on Apple/Android/ Windows only? yes System font, system styles Dynamic Type for free no (web or cross-platform) Is long reading the core job? articles, books, notes, docs yes Screen serif for body + system or sans for UI no Do you need a distinctive brand voice? yes Display face for headings, neutral face for everything else no System stack, or one screen sans (Inter, IBM Plex Sans, Source Sans 3) Spend the time on size, spacing and hierarchy instead.
A default decision path. Most solo products end at the first or last box. Leave them only for a reason you can write in one sentence.

The function checklist

Before committing to any face, check that it has: at least regular, medium or semibold, and bold (four weights is comfortable; a variable font is better); true italics if you set prose; tabular and lining figures (Chapter 13); the punctuation and symbols you use (₹, €, arrows, ×, curly quotes); every script your users write in; good hinting or rendering on Windows if you have Windows users; and a licence that covers how you ship (web, app, ePub, video).

Good free families for screens

FamilyOriginBest forNotes
InterRasmus Andersson, 2017Dense UI, dashboards, numbersTall x-height, many OpenType features (tabular figures, slashed zero, alternates), variable; a Display optical size arrived with version 4
IBM PlexIBM with Bold Monday, 2017Products that need sans, serif and mono that matchSuperfamily with several scripts, including Devanagari, Arabic and others
Source Sans 3 / Source Serif 4Adobe (Paul D. Hunt; Frank Grießhammer)Humanist UI, readable serifSource Serif 4 has an optical-size axis; this page’s body text uses it
LiterataTypeTogether for Google Play BooksLong reading on screensDesigned for e-reading; variable with optical sizes since version 3
CharterMatthew Carter, 1987Sturdy, compact body serifBuilt for low-resolution output; freely licensed; Butterick recommends it as a good free serif
iA Writer Mono / Duo / QuattroInformation Architects, from IBM Plex MonoWriting tools, focused editorsDuo widens a few letters (m, w and friends) to soften monospace’s unevenness; Quattro goes further toward proportional; open licence
Atkinson HyperlegibleBraille Institute, 2019Accessibility-first products, codesExaggerated letter differences for low-vision readers
LexendBonnie Shaver-Troup, Thomas JockinReading-support contextsWidth variants designed around reading-proficiency research by its creators; treat claims as promising, not proven
Public SansU.S. Web Design SystemNeutral, civic, government-like UIDerived from Libre Franklin; strong, plain, free
NotoGoogleCoverage for nearly every scriptUse as a fallback or as the main family for multilingual products
Lab: shortlist tester

Il1 O0 rn m · aces 38B · ₹1,234.50

NotificationsDaily summary

Your draft was saved two minutes ago. Changes sync across devices when you are online, and earlier versions stay in History for 30 days.

Drop the size to 12px and switch between Inter, Jost and Playfair. Watch the test string and the paragraph: which faces keep l, I and 1 apart, and which turn grey and spotty? That is your shortlist filter.
Don't
9:41 Settings Wi-FiHome BluetoothOn Text sizeLarge
Fighting the platform. A custom face inside native chrome looks off next to the status bar and system sheets, and loses Dynamic Type.
Do
9:41 Settings Wi-FiHome BluetoothOn Text sizeLarge
Belonging. In native UI, the system face is the voice users trust. Express brand in content, icon and colour instead.
Key idea

Function and cost decide the shortlist; taste decides between the survivors.

For the solo creator

A good rule: native app, use the system font and its text styles, full stop. Web app, start with the system stack; switch to one open-licence family (self-hosted, subset, variable) only if you can say in one sentence what it does that the system font doesn’t. Every family you add is something you maintain forever.

Do

  • Check weights, italics, figures, symbols, scripts and licence before falling in love.
  • Test at your smallest real size on Windows and on a phone.
  • Prefer variable fonts to cut files and get in-between weights.

Don't

  • Ship SF Pro as a webfont; its licence restricts it to Apple platforms. Use system-ui instead.
  • Pick a family missing ₹, curly quotes or your users’ script.
  • Choose a face because a famous brand uses it.

In the wild

  • Linear2019 onward
    Built its dense, crisp UI on Inter, a free screen family with tall x-height and tabular figures. A free, well-engineered family can carry a premium-feeling product.
  • Google Play BooksLiterata, 2015
    Commissioned a reading face from TypeTogether instead of using the UI font for book text. Reading and interface are different jobs and may deserve different faces.
  • Things 3, Apple NotesApple platforms
    Both use the system font and system text styles, and both scale with the user’s preferred text size. Native apps gain more from the system face than any custom font could give.

Common mistakes

Custom font in a native app

It is the easiest way to feel “branded”.

Use system text styles in native apps; if you must use a custom face, scale it with the platform’s font metrics APIs so it still respects user text size.

Missing glyphs discovered in production

You tested with English placeholder copy.

Keep a test string with ₹ € × → “ ” ’ – … and a line in each script you support. Check every candidate face against it.

Too many weights loaded

“Just in case”, nine static weights and their italics ship to every visitor.

Load one variable file, or two to three static weights you actually use. Audit with the browser’s network panel.

Check yourself

You are building a cross-platform web app for invoices used by small shops in India. Which choice is soundest?

Exercise 5.1 60 minutes · on your own product

Write your type decision record

  1. List your product’s text jobs: UI labels, body or long text, numbers or tables, code or IDs, headings or brand.
  2. For each job, write the minimum function requirement (sizes, figures, scripts, weights).
  3. Shortlist up to three candidates (including the system font) and test each with the shortlist lab above and your real screens.
  4. Write a half-page decision: chosen faces, the jobs each does, what you rejected and why, licence, and how it is loaded.
You're done when: you have a one-page type decision record you could hand to a future you in a year.
BeginnerCompetentStrong
A chosen font with a reason like “it looks clean”.Requirements listed and checked; rejections explained.Decision covers loading, licence, fallbacks and scripts, and was tested on Windows and at user-enlarged sizes.
6

Pairing, superfamilies and licences

Taught by Erik Spiekermann, with Matthew Butterick

One family is usually enough; when you pair, combine clear contrast in structure with shared proportions, and give each face a distinct job.

Pairing advice is full of folklore (“always pair a serif with a sans”). The underlying logic is simpler. Two faces on one screen should either be clearly the same (one family) or clearly different (contrasting structure). The failure zone is in between: two faces that are almost alike, so the reader senses a difference but can’t tell what it means. That reads as a mistake.

SameDifferent One family weights, sizes Aa Aa Conflict zone two similar sans Aa Aa Clear contrast serif + sans, matched x-height Aa Aa
Be clearly same or clearly different. Nearly-alike faces send a signal with no meaning.

Rules that actually explain pairings

  1. Start with one family. A good family with three or four weights and italics gives you more hierarchy than most products need (Chapter 9).
  2. If you pair, contrast structure. Serif with sans, or a display face with a text face. Not two neo-grotesques.
  3. Share proportions. Faces with similar x-height ratio and width sit comfortably on the same line and in adjacent blocks. Mismatched x-heights make one look shrunken.
  4. Share an era or a construction logic when possible. A humanist sans (pen proportions) pairs naturally with an old-style or modern humanist serif. A geometric sans sits well with a didone or a geometric slab.
  5. Give each face a job. “Serif for reading, sans for interface” or “display for page titles only”. If you can’t state a face’s job, you don’t need it.
  6. Prefer superfamilies. IBM Plex, Source, Noto and Roboto (Roboto, Roboto Slab, Roboto Mono, Roboto Serif) were designed to work together, with matched metrics. The pairing work is already done.
Same 34px: x-heights clash read read Garamond looks a size smaller. Adjusted: Garamond at 40px read read Matched by eye, not by number. CSS can help: font-size-adjust keeps x-height consistent across fallbacks and pairs.
Match apparent size. When two faces share a line or a screen, size them by x-height. The CSS property font-size-adjust does this numerically for fallbacks and mixed faces.
Don't

Monthly summary

You saved ₹4,200 this month, mostly on groceries. Your largest expense was rent.

Inter heading, Plex body. Two similar grotesques: the reader feels a shift but it carries no meaning.
Do

Monthly summary

You saved ₹4,200 this month, mostly on groceries. Your largest expense was rent.

One family, two weights. Hierarchy from size and weight alone. Simpler, faster to load, more coherent.

Licensing basics

A font is software, and its licence says where you may use it. You will meet four common situations:

LicenceWhat it allowsWatch for
SIL Open Font License (OFL)Use, embed in apps and websites, modify and redistribute, including commercially. Most Google Fonts, Inter, IBM Plex, Source, Literata, iA Writer fonts, Atkinson Hyperlegible.You can’t sell the font on its own. “Reserved Font Names” mean a modified version must be renamed.
Apache 2.0Similar freedoms; some Google families were released under it, including the original Roboto.Keep the licence notice with the files.
Commercial (desktop, web, app, ePub)Separate licences per use: desktop for making designs, web by pageviews or domains, app by number of apps or installs.A desktop licence does not let you embed the font in your app or on your website.
Platform fonts (SF Pro, Segoe UI)Use through the OS. Apple’s SF licence covers designing and developing for Apple platforms.Don’t ship them as webfonts or in non-platform builds; reference them via system font stacks.

Hosting also matters. Loading fonts from a third-party CDN sends your visitors’ IP addresses to that service; in 2022 a German court found that embedding Google Fonts from Google’s servers without consent violated GDPR. Self-hosting open-licence fonts avoids the issue and is usually faster anyway (Chapter 16).

Watch out

“Free for personal use” fonts from download sites are not free for your product. If the licence isn’t OFL, Apache or a commercial licence you bought for your use case, don’t ship it.

For the solo creator

Keep a /fonts/LICENSES folder in your repo with each font’s licence file and a one-line note: where it came from, version, what it covers. It takes five minutes and saves a frightening afternoon if a buyer, an app store reviewer or a lawyer ever asks.

Do

  • Try one family first; add a second only with a named job.
  • Pair across structure with similar proportions.
  • Keep licence files with font files and self-host open fonts.

Don't

  • Pair two similar sans serifs or two similar serifs.
  • Use three or more families in product UI.
  • Assume “free download” means free to embed.

In the wild

  • IBM PlexIBM, 2017
    Sans, Serif, Mono, condensed widths and many scripts in one open superfamily, so products can mix them without pairing problems. Superfamilies remove pairing risk.
  • NotionPage styles
    Lets users switch a page between Default (sans), Serif and Mono styles, each a single coherent voice rather than mixed fonts. Offer voices, not font soup.
  • The GuardianGuardian Egyptian, 2005
    A single custom family with headline and text cuts in serif and sans styles (Paul Barnes and Christian Schwartz) gives the paper its voice across print and digital. A designed family is the professional answer to pairing.

Common mistakes

Near-miss pairings

You liked one font for headings and another for body, and both are clean sans serifs.

Pick one of them for both roles, and create contrast with weight and size.

Font from a template, licence unknown

A UI kit or theme came with fonts bundled.

Identify every font in your build and find its licence; replace anything unclear with an OFL equivalent.

Check yourself

Your landing page uses Playfair Display for the hero, Inter for UI, Lora for testimonials and Roboto for the footer. What is the best move?

Connect the ideas · Part two recap

Recall Chapter 2 (anatomy). You pair Literata body text with a geometric sans for captions, and captions look tiny next to the body even at the same px. Why, and what fixes it?

Exercise 6.1 45 minutes · on your own product

Pairing audit and licence folder

  1. List every font family your product ships (inspect the network tab or your bundle).
  2. Write each family’s job in one sentence. Any family without a clear job is a candidate for removal.
  3. If you have two faces on one screen, set them side by side on one baseline and adjust sizes until x-heights relate deliberately.
  4. Create a licence folder with each font’s licence and source.
You're done when: your product uses one or two families with written jobs, sizes are x-height matched, and every font has a licence on file.
BeginnerCompetentStrong
Fonts listed.Jobs written, one redundant family removed or planned for removal.X-heights matched, licences filed, and bundle size measured before and after.
Part three

Setting text

Choosing a face is a one-time decision. Setting it is what you do on every screen: size, line spacing, line length, a scale of sizes, hierarchy, rhythm and alignment. This Part is the heart of the guide, and it has the most labs. Use them; the numbers become intuition only through your eyes.

7

Size, leading and measure

Taught by Robert Bringhurst, with Matthew Butterick

Body text reads best at 16–20px on screens, with line-height around 1.4–1.6, on lines of 45–75 characters; and the three numbers depend on each other.

These are the three settings that decide whether a paragraph is comfortable. They are not independent. A bigger size needs a longer line in px to keep the same characters per line. A longer line needs more leading so the return sweep (Chapter 4) can find the next line. A face with a tall x-height looks bigger and needs more leading than one with a small x-height. Tune them together.

Size: start at 16, often go higher

Browsers default to 16px, and that is a floor for body text on the web, not a target. Butterick suggests 15–25px for web body text; many reading-focused sites sit at 18–21px. On iOS the default Body text style is 17pt; Android’s Material body sizes are around 14–16sp. People hold phones closer than they sit to laptops, so similar numbers work on both. Text smaller than about 12–13px should be rare and never essential.

Leading: the space between lines

“Leading” comes from the strips of lead typesetters put between lines of metal type. In CSS it is line-height, best written unitless (1.5, not 24px) so it scales with size. For body text, 1.4–1.6 is the usual band; Butterick suggests 120–145% of the point size, and WCAG’s enhanced criterion asks for at least 1.5 within paragraphs. Use the low end for short lines and small x-heights, the high end for long lines and tall x-heights. Headings need less: 1.1–1.25, because large sizes already create space and loose headings fall apart into separate lines.

Measure: characters per line

Bringhurst gives the classic range: 45 to 75 characters per line (counting letters and spaces) for single-column text, with around 66 often cited as ideal. Shorter lines force constant return sweeps and choppy reading; longer lines make the sweep long and error-prone. In CSS set it with max-width in em or ch. Note that ch is the width of the digit zero, which is usually wider than an average letter, so 66ch typically gives somewhat more than 66 real characters. Test with real text, as the lab below does.

Too long
~120 characters, leading 1.2
Lost return sweeps. The eye overshoots or repeats lines.
Comfortable
~65 characters, leading 1.5
Easy rhythm. Lines short enough to sweep, spaced enough to land.
Too short
~25 characters
Choppy. Constant sweeps, ragged edge dominates, phrases break.
Lab: readability (size, leading, measure, face)

Reading is not a smooth glide. Your eyes jump a few words at a time, pause for a fraction of a second, and at the end of every line make a long sweep back to the left edge to find the next one. When lines are too long, that sweep misses; when they are packed too tightly, the target is too small to hit. Comfortable text is not about a beautiful font so much as about three numbers chosen together: how big the letters are, how much air sits between the lines, and how many characters each line carries before it turns.

Characters per line: –Line height: –Suggested for this measure: –
Try this: set width to 900px and line-height to 1.2, then read the paragraph. Now bring width down until the counter says about 65, raise line-height to the suggestion, and read again. Then switch to EB Garamond and notice you want 2px more size for the same comfort. (On a phone the screen limits the width, which is the point: phones naturally produce 35–45 characters.)

Leading relative to measure

The lab’s suggestion follows a simple principle: the longer the line, the more leading it needs. A 40-character mobile column can live at 1.4; a 75-character desktop column wants 1.6 or more. Text with a tall x-height (Inter, Atkinson, Verdana) looks tighter at the same line-height, because the gap between lines (from baseline to the next line’s x-height) is smaller; give it 0.05–0.1 more.

Characters per line line-height 3045607590 1.31.51.7 comfortable measure: 45–75 long lines need air short lines can be tighter
A rule of thumb, not a law. Roughly +0.1 of line-height for every 15–20 extra characters per line. Then adjust by eye for the face’s x-height.

Paragraph spacing or indent, never both

Paragraphs need a signal that a new one has begun. Either add space between them (on screens, typically 0.75–1em, smaller than a full blank line is fine), or indent the first line (1–2em) with no extra space, as books do. Using both double-signals and wastes space. On screens, and especially in UI and documentation, spacing is the norm because text is scanned as much as read. First-line indents suit continuous reading like fiction and long essays.

Don't

The parcel left the warehouse this morning and is with the courier now.

You will get a message when it is out for delivery.

Indent plus space. Two signals for one job.
Do

The parcel left the warehouse this morning and is with the courier now.

You will get a message when it is out for delivery.

Space only. The screen convention: calm, scannable blocks.
Key idea

Size, leading and measure are one decision with three dials. Move one, re-check the other two.

For the solo creator

Write three tokens and use them everywhere: --text-body: 1.125rem (18px), --leading-body: 1.55, --measure: 34em. Put max-width: var(--measure) on every container of running text, not on the page. The page can be wide; paragraphs shouldn’t be.

Do

  • Use unitless line-height so it scales.
  • Limit running text to 45–75 characters, measured with real text.
  • Tighten leading for headings (1.1–1.25).

Don't

  • Let paragraphs stretch across a 1440px monitor.
  • Set body text below 16px on the web to “fit more”.
  • Inherit body line-height (1.5) into 40px headings.

In the wild

  • WikipediaVector 2022 skin
    The 2022 redesign introduced a maximum width for article content after years of full-width text on large monitors. Even the web’s biggest reference work found that limiting line length helps reading.
  • Instapaper & Reader modes2008 onward
    Reading modes in Instapaper, Safari Reader and others strip a page and re-set it with a larger size, generous leading and a narrow column. People install products just to fix size, leading and measure.
  • iA WriterInformation Architects
    Keeps the writing column at a comfortable measure and scales type with the window, so line length stays reasonable across devices. Line length can be a product feature, not just a style.

Common mistakes

Full-width text on desktop

The layout was built mobile-first and the container simply grows.

Cap text containers with max-width in em or ch; let images and tables go wider if needed.

Leading in px

Copied from a design tool that shows line-height in px.

Convert to unitless ratios; px leading breaks when the user or a component changes font size.

One line-height for everything

A global line-height: 1.5 on body is inherited by headings.

Set line-height per text style: body 1.5–1.6, UI labels 1.3–1.4, headings 1.1–1.25.

Check yourself

Your help center article is set at 17px, line-height 1.5, in a 720px column of Inter. The counter shows about 88 characters per line. Readers find it tiring. Which fix keeps the layout and improves reading most?

Exercise 7.1 45 minutes · on your own product

Set your body text tokens

  1. Find the longest real paragraph in your product and paste it into the readability lab (or a local HTML file).
  2. Choose your face, then find the smallest size you can read comfortably for five minutes. Add 1px.
  3. Set measure to 60–70 characters and choose line-height from the suggestion, then adjust by eye.
  4. Write the three tokens into your codebase and apply them to all running text containers.
You're done when: your product has body size, leading and measure tokens, applied everywhere text runs longer than two lines, with before/after screenshots.
BeginnerCompetentStrong
Values copied from this chapter.Values tuned by eye with real text, applied globally.Values tested on phone, laptop and a large monitor, with a mobile variant (smaller measure, slightly tighter leading).
8

Type scales: a few sizes, related

Taught by Tim Brown (modular scales), with Robert Bringhurst

Pick five to seven sizes related by a consistent ratio, give each a job, and use nothing else; the relationship between sizes is what makes hierarchy feel intentional.

Look at a product built without a scale and you’ll find 11px, 12px, 13px, 14px, 15px, 16px, 17px, 18px, 20px, 22px, 24px and 28px, each chosen once for one component. The result looks slightly off everywhere, because neighbouring sizes are too close to read as different levels and too far to read as the same. A scale fixes this by making every size a deliberate step.

Modular scales

Bringhurst described the classical scale of sizes used by printers since the sixteenth century, and in 2011 Tim Brown’s article “More Meaningful Typography” (A List Apart) and his modularscale.com tool popularised the idea for the web: start with a base size and multiply by a ratio. With a 16px base and a 1.25 ratio you get 16, 20, 25, 31.25, 39 and so on; dividing gives 12.8 and 10.24 below. The ratios have musical names because they are the same intervals:

RatioNameFeelGood for
1.125Major secondVery gentle stepsDense apps, dashboards, mobile
1.2Minor thirdGentle, quietMost product UI
1.25Major thirdClear but calmDocs, content apps, general web
1.333Perfect fourthConfidentEditorial sites, blogs
1.5Perfect fifthDramaticLanding pages, marketing
1.618Golden ratioVery dramaticPosters, hero sections; too steep for apps
Base 16px, six steps up 1.2 16 → 48px: quiet steps 1.5 16 → 122px Body Title Heading Page Body Title Heading 1.2 (top) suits apps; 1.5 (bottom) runs out of screen in four steps.
The ratio sets the drama. Steep ratios produce memorable headlines and very few usable steps; gentle ratios give many close steps for complex UI.
Lab: type scale generator
/* CSS tokens appear here */
Six named steps are generated from your base. Faded rows are sizes you probably don’t need. Copy the tokens into your stylesheet. Try 1.5 with base 16 and see how quickly sizes become too big for an app screen; then try 1.2.

How many sizes you really need

Most products work with five to seven sizes: caption or small, body, a large body or subtitle, two or three heading levels, and possibly one display size for marketing. Material Design 3 defines fifteen named roles (display, headline, title, body and label, each in large, medium and small), and Apple’s iOS text styles define eleven (from Large Title at 34pt down to Caption 2 at 11pt, with Body at 17pt). Notice that Apple’s steps aren’t a strict ratio: they are hand-tuned, with tighter steps in the text range and bigger jumps at the top. That is a good model. Use a ratio to generate candidates, then round and adjust.

Large Title34 Title 128 Title 222 Title 320 HeadlineBody17 / 17 Callout16 Subheadline15 Footnote13 Caption 112 Caption 211
Apple’s hand-tuned scale (default “Large” setting, points). Close steps in the text range, a big leap to Large Title. Users can scale all of these together.

Fluid scales

On the web, a heading that is right at 1440px is often too big at 375px. You can use a gentler ratio on small screens and a steeper one on large screens, interpolating with CSS clamp(): for example font-size: clamp(1.75rem, 1.2rem + 2.5vw, 3rem) for a page title. Keep body text nearly fixed (it should not shrink on phones) and let display sizes flex.

Don't
Project settings General Name and description Visible to collaborators Last edited 2 days ago 16 / 15 / 14 / 13 / 12.5: five sizes, no levels
Sizes too close. Each is different, none reads as a level.
Do
Project settings General Name and description Visible to collaborators Last edited 2 days ago 22 / 14 / 12: three sizes, clear levels
Fewer, further apart. Same-level items share a size; weight and colour do the rest.
Key idea

A scale is a vocabulary. Small vocabularies are easier to speak consistently.

For the solo creator

Name sizes by role, not by number: --text-small, --text-body, --text-title, --text-heading, --text-display. Then a design change (“body up one step”) is one edit, and you can’t accidentally invent a 15.5px.

Do

  • Generate sizes from a ratio, then round and hand-tune.
  • Use gentle ratios (1.125–1.25) in apps, steeper ones in marketing.
  • Keep five to seven sizes, each with a named job.

Don't

  • Introduce a new size to fix one component.
  • Use adjacent sizes 1px apart for different levels.
  • Use the golden ratio for an app because it sounds principled.

In the wild

  • Apple HIG text stylesiOS, iPadOS
    Eleven named styles that scale together with Dynamic Type. Developers pick a role (Headline, Body, Footnote), not a size. Roles survive redesigns and user scaling; raw sizes don’t.
  • Material Design 3Google, 2021
    Fifteen roles in five groups, with tokens for size, line-height, weight and tracking per role. A type role is a bundle: size, leading, weight and tracking travel together.
  • Tailwind CSSDefault theme
    Ships a fixed set of named sizes (text-xs to text-9xl), each paired with a default line-height. Even utility-first CSS works from a closed scale.

Common mistakes

Scale with too many steps in use

The generator outputs ten sizes, so all ten get used.

Generate many, adopt few. Delete unused tokens so they can’t creep in.

Size carries every level

The only tool used for hierarchy is size, so the scale needs many close steps.

Use weight and colour for minor distinctions (Chapter 9); reserve size changes for real level changes.

Check yourself

You’re designing a dense analytics app used on laptops. Which scale is most sensible?

Exercise 8.1 60 minutes · on your own product

Collapse your sizes

  1. List every font size in your codebase (search CSS for font-size or your text style definitions). Count them.
  2. Use the generator to create a scale from your body size with a ratio that fits your product type.
  3. Map each existing size to the nearest scale step, and name each step by role.
  4. Refactor, then compare before/after screenshots of three screens.
You're done when: your product uses at most seven named sizes, and the before/after count is written down (for example “14 sizes → 6”).
BeginnerCompetentStrong
Scale generated, partly applied.All text uses named steps; count reduced by half or more.Steps hand-tuned, line-height and weight defined per role, fluid display sizes on web.
9

Hierarchy without shouting

Taught by Massimo Vignelli, with Erik Spiekermann

Size is only one of six levers for typographic hierarchy; calm interfaces use weight, colour, case, space and position for most distinctions, and change only one or two levers per level.

Vignelli was famous for working with very few typefaces and a few sizes, and still producing rich, clear hierarchy. The trick is that hierarchy is about difference, and size is the loudest, most space-hungry way to make a difference. In a dense product screen you have many small distinctions to make (title vs metadata, label vs value, active vs inactive), and if all of them use size you end up with a dozen sizes and a noisy page. See Visual Design for hierarchy in layout; this chapter covers the typographic levers.

1 · SIZE InboxInbox loudest; costs space 2 · WEIGHT InboxInbox strong, same space 3 · COLOUR InboxInbox quiet; keep contrast 4 · CASE + TRACKING INBOXInbox labels and overlines 5 · SPACE Inbox Archive gap = group 6 · POSITION First = important top-left reads first Rule: change one or two levers per level. Changing all six at once is shouting.
Six levers. Size and weight add emphasis; colour and space subtract it. Most UI hierarchy can be built from weight and colour alone, at one or two sizes.

Emphasis by subtraction

Beginners make important things bigger and bolder. Experienced designers more often make unimportant things quieter: smaller, lighter, muted grey. The effect is the same contrast, but the page gets calmer instead of louder. A list item with a 15px semibold title and a 13px muted line of metadata has clear hierarchy without any big type.

Be careful with grey. Muted text still has to meet contrast requirements (4.5:1 for normal text under WCAG AA); “subtle” #AAA on white fails. Use one or two defined text colours (primary and secondary), not a gradient of greys. See Accessible & Inclusive for the contrast details.

Hierarchy by size vs hierarchy by weight and colour
Invoices
Acme Studio
INV-2041 · Due 12 March
₹48,000
Lotus Bakery
INV-2040 · Paid
₹6,250
Northwind Ltd
INV-2039 · Overdue
₹1,12,500
Without: everything is big and bold, so nothing stands out. Five sizes and three weights compete. The overdue invoice is invisible.

Weights: fewer than you think

Two weights (regular and semibold, or regular and bold) handle most interfaces. Add medium only if your face’s regular looks thin at small sizes. Light and thin weights are for large display sizes; at 14px on a Windows laptop they disappear. Avoid “faux bold”: if you set font-weight: 600 but haven’t loaded a 600 weight, the browser smears the regular glyphs to fake it, and the result is blotchy.

Italics and emphasis

In prose, emphasis is italic (a quiet change in texture that doesn’t break the line’s colour). In UI, emphasis is weight, because italics in short labels look accidental. Underline is reserved for links on the web, and colour alone is never the only signal (some users can’t see it).

Don't

Remember: never share your recovery key with anyone, including our support team.

Every lever at once. Bold, underline, caps and italics in one sentence cancel each other out.
Do

Never share your recovery key with anyone, including our support team.

One emphasis, where it surprises. The surprise is “including support”, so that is what gets italics.
Key idea

Make the important things clear by making everything else quieter.

For the solo creator

Define exactly two text colours (--text and --text-secondary) and two weights (400 and 600). Try to build every new screen with only these plus your scale. When you feel the urge for a third grey or a bold-italic, treat it as a sign the content structure needs work, not the type.

Do

  • Use weight and colour for minor levels, size for major ones.
  • Mute secondary information rather than shouting primary.
  • Load the real weights you set in CSS.

Don't

  • Stack bold, caps, colour and underline on one phrase.
  • Use light or thin weights for small text.
  • Use more than two greys for text.

In the wild

  • Apple Mail & GmailInbox lists
    Unread messages are shown mainly by weight (bold sender and subject), not by size, so read and unread rows keep the same rhythm. Weight changes state without breaking the layout.
  • Stripe DashboardTables and detail views
    Detail views pair small labels with regular-weight values and muted secondary lines, building dense but calm screens from very few sizes. Overlines and muted metadata replace headings in dense UI.
  • Vignelli’s NYC Subway manualUnimark, 1970
    A tightly limited palette of type sizes and one family for an entire signage system. Constraint makes a system learnable.

Common mistakes

Everything is bold

Each element was emphasized when it was built, in isolation.

Start every screen at regular weight; add semibold only to the one item per group the eye should land on first.

Grey that fails contrast

Light grey looks elegant on a good monitor.

Check secondary text at 4.5:1 or above; if it fails, darken it and use size or weight to separate instead.

Check yourself

In a task list, completed tasks need to recede and overdue tasks need to stand out. All rows are 15px regular. What is the calmest effective treatment?

Exercise 9.1 40 minutes · on your own product

One size, many levels

  1. Pick your busiest list or card screen.
  2. Rebuild it (in code or a quick mock) using a single font size for all text in the list rows. Use only weight, colour, case and space to create hierarchy.
  3. Compare with the original. Where did you need size? Add it back only there.
You're done when: you have a version with at most two sizes in the list and clear hierarchy, plus a note on which distinctions truly needed size.
BeginnerCompetentStrong
Single-size version made but hierarchy unclear.Clear hierarchy from weight and colour; contrast checked.Shipped, with fewer sizes and weights than before and no loss of clarity in a quick test with someone else.
10

Vertical rhythm and spacing

Taught by Robert Bringhurst, with Josef Müller-Brockmann

Space between text elements should come from a small set of related values, and space above a heading should be larger than space below it, so headings belong to what follows.

Bringhurst compares the page to music: the rhythm of lines and spaces should be steady, and departures from it should be meaningful. In print, typographers lock every line to a baseline grid so lines on facing pages align. On screens, a strict baseline grid is harder (and less valuable), but the underlying idea is essential: spacing should be systematic, and it should express relationships.

The heading proximity rule

A heading labels the content below it, so it should sit closer to that content than to the content above. A common ratio is about 2:1 (for example 32px above, 12–16px below). When the spaces are equal, the heading floats ambiguously between two sections, and users have to read it to know where it belongs. This is the Gestalt principle of proximity (see The Human Mind) applied to type.

Don't
28 31 Which section owns the heading?
Equal spacing. The heading floats between sections.
Do
40 12 The heading clearly starts a section.
More above, less below. Proximity does the grouping.

A spacing system from your line-height

The simplest rhythm on screens: derive spacing from a base unit (commonly 4px or 8px) and keep line-heights on that unit too. If body text is 18px with line-height 1.5, a line is 27px, which doesn’t sit on a 4px grid; 18px × 1.556 ≈ 28px does. Many teams round line-heights in px to multiples of 4 for each text style (body 28, small 20, title 32, heading 40) and use spacing tokens of 4, 8, 12, 16, 24, 32, 48, 64. Then everything snaps to one invisible rhythm and nothing looks “a bit off”.

Getting started Body baselines land every 28px, the line height. Headings take two units; gaps are whole units. A new paragraph after one empty unit of 28px. The rhythm stays steady down the page. 28px rows 1 unit gap
A grid of 28px rows. Strict baseline grids are useful for long reading pages; for app UI, consistent spacing tokens give most of the benefit with less fuss.

Why exact baseline grids are hard on the web

CSS centres text inside its line box: half the extra leading goes above, half below (“half-leading”), and the font’s own ascent and descent metrics add more invisible space. So the visible top of a capital letter is not at the top of the box. That is why a button label can look slightly low even when padding is “equal”, and why aligning text to an icon needs care. Tools such as Capsize compute trims from font metrics, and newer browsers support the text-box properties (text-box-trim and text-box-edge) that cut the box down to cap height and baseline. Use them for precise component alignment; don’t chase a perfect page-wide baseline grid in a complex app.

Hxg Line box: half-leading (yellow) + font metrics Hxg Trimmed to cap height and baseline Defaulttext-box trimmed
Invisible space around text. It is why “equal padding” often looks unequal. Trim it when precise alignment matters (buttons, icon rows, badges).
For the solo creator

Don’t build a baseline-grid framework. Do this instead: spacing tokens on a 4px base, line-heights per text style rounded to 4px, and the 2:1 heading rule. Turn on a 4px grid overlay in your browser dev tools once a month and look for strays.

Do

  • Put more space above headings than below.
  • Use a small set of spacing tokens tied to a base unit.
  • Trim text boxes (or nudge) when aligning text with icons.

Don't

  • Use arbitrary margins like 13px or 22px.
  • Let heading margins equal paragraph margins.
  • Force a rigid baseline grid onto dense, mixed-size UI.

In the wild

  • Material Design4dp/8dp grid
    Components and type line-heights are designed to snap to a 4dp baseline, with spacing in 8dp steps. A shared unit for type and layout keeps a huge system consistent.
  • GOV.UK Design SystemSpacing scale
    Publishes a responsive spacing scale and uses consistent heading margins across thousands of pages. Rhythm can be enforced with tokens, not willpower.
  • CapsizeSeek, open source
    Uses font metrics to trim the space above capitals and below the baseline, so text boxes align precisely to layout. Invisible metric space is a solvable engineering detail.

Common mistakes

Margins on both sides of everything

Each component brings its own top and bottom margin, and they stack unpredictably.

Use a layout-level rule (for example a stack with gap, or margin only on top of following siblings) so spacing comes from one place.

“Equal padding” that looks unequal

Text line boxes include invisible ascent and descent space.

Judge visually, or trim with text-box/Capsize; adjust by 1–2px if needed.

Check yourself

In your docs, section headings have 24px margin above and 24px below. Users skim and sometimes read the wrong section. Best fix?

Exercise 10.1 40 minutes · on your own product

Spacing census

  1. On one long screen, measure every vertical gap between text elements (dev tools or a screenshot ruler).
  2. List the unique values. Map each to a token on a 4px base.
  3. Fix heading spacing to roughly 2:1, refactor gaps to tokens, and compare before/after.
You're done when: the screen uses only spacing tokens, headings follow the proximity rule, and you have before/after screenshots side by side.
BeginnerCompetentStrong
Gaps measured.All gaps tokenized, heading rule applied.Tokens adopted product-wide, with line-heights rounded to the base unit.
11

Alignment, rag and wrapping

Taught by Matthew Butterick, with Robert Bringhurst

On screens, set text flush left and ragged right by default; justify only with good hyphenation and a generous measure, and let the browser balance headings and avoid stranded last words.

Justified text, with both edges straight, looks orderly in books because book typesetting engines adjust spacing across a whole paragraph, hyphenate carefully, and may even subtly adjust letter spacing. Browsers mostly do something simpler: they break lines one at a time and stretch the word spaces on each line to fill it. On narrow columns, that produces irregular gaps and sometimes “rivers”, channels of white that run down through the paragraph and pull the eye vertically.

Justified, narrow, no hyphenation Ragged right Uneven gaps line up into a river. Even spaces; the ragged edge is calm.
Rivers come from stretched spaces. Ragged right keeps word spacing constant, which is what the eye actually relies on.

When justification is fine

Justified text can work on screens when three conditions hold: the measure is generous (60+ characters), hyphenation is on (hyphens: auto with a correct lang attribute on the page or element), and the content is continuous reading (an e-book, a long essay) where a book-like texture is part of the experience. E-readers such as Kindle justify by default with hyphenation. For UI, docs and anything narrow or mixed with code and links, ragged right is better. WCAG’s enhanced criterion (1.4.8) lists “not justified” among its visual presentation requirements, because uneven spacing makes reading harder for some people, including many dyslexic readers.

Lab: justified vs ragged, with hyphenation

Typographers have argued about justification for centuries. In a well-made book, the compositor balances spacing across the whole paragraph and hyphenates carefully, so the texture stays even. Browsers typically break lines one at a time and stretch the spaces, which in narrow columns opens irregular gaps and occasionally a river of white running down the page. Hyphenation helps, because breaking long words gives the line breaker more choices. Characteristically, administrative, internationalization and responsibility are the kind of words that cause trouble.

Start at 300px, justified, hyphenation off: look for big gaps. Turn hyphenation on and watch them shrink. Then widen to 600px and notice justification becomes acceptable. “Pretty” wrapping (where supported) avoids a single stranded word on the last line.

Shaping the rag

Ragged right isn’t carefree. A good rag ripples gently; a bad one has deep notches or a staircase shape. On the web you can’t hand-tune each paragraph, but you can help: keep the measure in range, enable hyphenation for long-word languages (German, Dutch) and narrow mobile columns, and use non-breaking spaces to keep small units together (“10 MB”, “Mr. Sharma”, “Chapter 7”).

Widows, orphans and stranded words

In print, an orphan is a paragraph’s first line left alone at the bottom of a page and a widow is its last line alone at the top of the next (definitions vary between sources, which is why many people just say “stranded lines”). On the web, the everyday problem is a single short word alone on the last line of a paragraph or heading (sometimes called a “runt”). CSS now helps: text-wrap: balance evens out line lengths in short blocks like headings and captions, and text-wrap: pretty asks the browser to avoid very short last lines in paragraphs. Balance is widely supported; pretty is newer, so treat both as progressive enhancement.

Don't

Your notes, exported to Markdown or PDF in seconds

Unbalanced heading. Full lines, then a stub (“seconds”) alone on the last.
Do

Your notes, exported to Markdown or PDF in seconds

text-wrap: balance. Lines of similar length; the heading reads as one shape.

Centred and right-aligned text

Centred text has two ragged edges, so every return sweep must find a new starting point. It works for short, symmetrical things (a dialog title, a two-line empty state, a poster headline) and fails for anything over about three lines. Right alignment is for numbers in tables (Chapter 13) and for labels hugging a value, not for paragraphs (in left-to-right languages).

Key idea

The eye trusts even word spacing more than straight edges. Keep the spaces even; let the edge breathe.

For the solo creator

Three lines of CSS cover most of this chapter: h1,h2,h3{text-wrap:balance}, p{text-wrap:pretty}, and html{lang} set correctly so hyphenation and quotes work when you need them. Add hyphens:auto only on narrow mobile columns or long-word languages.

Do

  • Default to left aligned, ragged right.
  • Balance headings and avoid stranded last words.
  • Use non-breaking spaces between numbers and units.

Don't

  • Justify narrow columns without hyphenation.
  • Centre paragraphs longer than three lines.
  • Fix rag by inserting manual line breaks that break on other screens.

In the wild

  • KindleAmazon
    Justifies book text with hyphenation by default, and some Kindle devices and apps let readers switch to left alignment. Justification is a book convention; offering ragged is a kindness.
  • GitHub, Notion, LinearDocs and issues
    All set long text flush left, ragged right, in UI-width columns. Product text is mixed (links, code, mentions); ragged handles it gracefully.
  • Chrome & Safari2023–2024
    Shipped text-wrap: balance, making balanced headings a one-line fix that previously needed JavaScript libraries. Check the platform before writing a workaround.

Common mistakes

Justified text on mobile

The desktop design was justified and nobody checked a 360px phone.

Use ragged right below a breakpoint, or never justify in UI at all.

Manual line breaks in headings

A <br> made the heading look perfect on your screen.

Remove it; use text-wrap: balance so the break adapts to every width.

Check yourself

You are building an e-reader for long novels and want a book-like feel. Which setting is most defensible?

Connect the ideas · Part three recap

A blog post is 17px, line-height 1.3, 100 characters per line, justified, with 9 sizes in use. You have 30 minutes. In which order do you fix it?

Exercise 11.1 30 minutes · on your own product

Wrap and rag pass

  1. Add text-wrap: balance to headings and text-wrap: pretty to paragraphs in your product.
  2. Find every centred or justified block longer than three lines and decide: keep (with reason) or change to left aligned.
  3. Search your copy for numbers followed by units and insert non-breaking spaces where a break would hurt.
You're done when: headings are balanced, no long paragraph is centred, and you have before/after screenshots at 360px and 1280px.
BeginnerCompetentStrong
CSS added.Alignment audited and fixed product-wide.Also checked in a second language or a long-word test string, with hyphenation set appropriately.
Part four

The details

Readers rarely notice correct punctuation, aligned figures or well-tracked capitals. They do notice, often without knowing why, when these are wrong: text looks cheap, numbers look jittery, labels look cramped. These chapters are small fixes with outsized effect on perceived quality.

12

Quotes, dashes and the small marks

Taught by Matthew Butterick, with Robert Bringhurst

Straight quotes, double hyphens and three dots are typewriter substitutes; real typography uses curly quotes, true apostrophes, the right dash for each job and a real ellipsis, except in code, where straight characters are correct.

Typewriters had a limited keyboard, so one key served for opening quotes, closing quotes, apostrophes, feet and inches. Computers inherited that keyboard. Butterick calls straight quotes and apostrophes the most visible sign of careless typography, because they look like what they are: a mechanical compromise. Your product’s microcopy is read millions of times. Getting these marks right costs almost nothing once you know them.

Typewriter Typographic Typewriter Typographic "Hi" “Hi” double quotes opening 66, closing 99 it's it’s apostrophe same glyph as closing single quote 5-10 5–10 hyphen for a range en dash: ranges, “to” a -- b a—b double hyphen em dash: a break in thought Wait... Wait… three periods ellipsis: one character, won’t split 5'11" 4x 5′11″ 4× quotes as primes, letter x primes, multiplication sign
Six pairs to learn by sight. Once you see them, straight quotes in a polished UI will bother you forever. That is the point.

The dashes

There are three common horizontal marks and they are not interchangeable. The hyphen (-) joins words (“well-known”, “sign-in page”) and breaks words at line ends. The en dash (–), about the width of an n, marks ranges and connections: “9–5”, “Mumbai–Pune”, “pages 12–18”. The em dash, about the width of an M, marks a strong break in a sentence (shown in the figure above). Many writers overuse the em dash; in UI copy, a colon, comma or full stop is often clearer. The minus sign (−) is a fourth mark, as wide as a plus sign, for negative numbers in data: −₹1,200 lines up with +₹1,200, while a hyphen looks short and weak.

Spaces you didn’t know existed

A non-breaking space (&nbsp;, U+00A0) looks like a normal space but forbids a line break, so “10 MB”, “₹ 500” (if you space it), “Fig. 3” and “iOS 18” never split across lines. A thin space (U+2009) is useful around some marks and between number groups in some locales. One space after a full stop, never two; the double space is another typewriter habit.

MarkUseMacWindowsHTML
“ ”Double quotesOption+[ , Option+Shift+[Alt+0147, Alt+0148&ldquo; &rdquo;
‘ ’Single quotes, apostrophe (’)Option+] , Option+Shift+]Alt+0145, Alt+0146&lsquo; &rsquo;
–En dash: rangesOption+HyphenAlt+0150&ndash;
(em)Em dash: breaksOption+Shift+HyphenAlt+0151&mdash;
…EllipsisOption+;Alt+0133&hellip;
×Multiplication, dimensionsCharacter ViewerAlt+0215&times;
′ ″Feet, inches, minutesCharacter ViewerCharacter Map&prime; &Prime;
−Minus signCharacter ViewerCharacter Map&minus;

In source code and string files you can also simply paste the Unicode characters; modern toolchains handle UTF-8. On iOS and many keyboards, long-pressing the quote or hyphen key offers these characters.

Lab: quotes and dashes fixer

Highlighted characters were changed. The fixer uses context: a quote after a space opens, after a letter it closes; a quote after a digit becomes a prime; a hyphen between digits becomes an en dash. It is a teaching tool with simple rules (it will misjudge some cases, such as phone numbers), which is exactly why you should know the rules yourself.

Where straight quotes are correct

Code, terminal commands, JSON, CSS, URLs and anything a user will copy into a technical context must keep straight quotes and hyphens. A curly quote in a shell command breaks it, and an en dash in a command-line flag fails silently. In your product, turn off smart punctuation in code inputs, password fields and API key fields (on iOS, smartQuotesType = .no and smartDashesType = .no; on the web, keep such content in <code> and don’t run text transforms on it).

Don't

Install the CLI:

npm install –g “rohit-cli”

“Smart” punctuation in a command. The en dash and curly quotes break the command when pasted.
Do

Install the CLI:

npm install -g "rohit-cli"

Code stays literal. Monospace, straight characters, in a code element that no text processor touches.

Other languages, other marks

Quote styles vary: German uses „low-high“ quotes, French uses «guillemets» with spaces inside, Japanese uses 「corner brackets」. Hindi text generally uses the same curly quotes as English. If you localize, don’t hard-code quote characters in templates; let translators include them in strings, or use the HTML <q> element with the CSS quotes property and a correct lang attribute.

For the solo creator

Do one pass now: search your UI strings for ", ', --, ... and digit-hyphen-digit, and fix them. Then add a lint rule or a pre-commit script that flags straight quotes in your strings file (not in code). Ten minutes of tooling saves you from ever thinking about it again.

Do

  • Use curly quotes and apostrophes in all user-facing prose.
  • Use en dashes for ranges and the minus sign for negative numbers.
  • Keep code and commands strictly straight.

Don't

  • Use a hyphen for ranges (“5-10”).
  • Type three periods for an ellipsis in UI strings.
  • Let autocorrect curl quotes in code fields.

In the wild

  • Apple platformsSmart Punctuation
    iOS and macOS curl quotes and convert double hyphens as you type, with a setting to turn it off and APIs for developers to disable it per field. Make correct punctuation the default, and give technical fields an escape.
  • SmartyPantsJohn Gruber, 2002
    A widely used text filter that converts straight quotes, double hyphens and triple dots into typographic punctuation, alongside Gruber’s Markdown. Automate punctuation at the content pipeline, then trust it.
  • Butterick’s Practical TypographyOnline book
    Devotes short, blunt chapters to straight and curly quotes, hyphens and dashes, and the ellipsis. The cheapest upgrade to any text is correct punctuation.

Common mistakes

Mixed straight and curly quotes

Some strings came from a design tool (curly), others typed in a code editor (straight).

Normalise all user-facing strings in one pass and lint them.

Backwards apostrophes

Auto-curling sees a quote after a space and opens it: ‘90s instead of ’90s.

Leading apostrophes in abbreviations (’90s, ’n’) always point like a 9 (a closing quote).

Curly quotes in copy-paste commands

A CMS or Markdown filter “smartened” everything, including code.

Exclude code spans and blocks from typographic filters, and test by pasting commands into a terminal.

Check yourself

Which string is correct for a pricing page?

Exercise 12.1 30 minutes · on your own product

Punctuation sweep

  1. Export or open your product’s user-facing strings (a strings file, i18n JSON or your templates).
  2. Search for ", ', --, ... and [0-9]-[0-9]. Fix each in prose; leave code alone.
  3. Add non-breaking spaces between numbers and units.
  4. Add a simple lint (a script or regex in CI) that warns on straight quotes in strings.
You're done when: a search for straight quotes in user-facing strings returns only intentional cases, and a lint prevents regressions.
BeginnerCompetentStrong
Main screens fixed by hand.All strings fixed; code and inputs excluded correctly.Lint in place, plus smart punctuation disabled in technical input fields.
13

Figures, small caps and OpenType features

Taught by Tobias Frere-Jones, with Edward Tufte and Rasmus Andersson

Most good fonts hide several versions of their numerals and other alternates; choose tabular lining figures for data, proportional or old-style figures for prose, and use real small caps and fractions instead of fakes.

Numbers are everywhere in products: prices, dates, counts, durations, versions. Fonts usually include at least two sets of digits, and many include four, selected with OpenType features. Using the right set is one of those details that makes an interface feel engineered rather than assembled.

PROPORTIONAL (pnum) TABULAR (tnum) LINING OLD-STYLE 1104.98 headings, UI text, prices in a sentence 1104.98 tables, counters, timers, columns 1104.98 numbers inside running prose 1104.98 rare: tables inside book-like text
Four figure styles. The lining row uses Source Serif 4; the old-style row uses Georgia, whose default figures are old-style (if Georgia isn’t installed, you’ll see lining figures there too). Lining figures sit at cap height; old-style figures rise and fall like lowercase letters, so they blend into prose. Note that font services often strip features like old-style figures when subsetting, so check the files you actually serve.

Tabular vs proportional

Proportional figures have individual widths (a 1 is narrow, a 0 is wide), which looks even in a sentence. Tabular figures all share one width, so digits line up in columns and a changing number (a timer, a progress counter, a stock price) doesn’t jiggle as it updates. In CSS: font-variant-numeric: tabular-nums. Fonts differ in their defaults: Inter defaults to proportional figures (tabular are one feature away), while the Google Fonts versions of Source Serif 4 and EB Garamond default to tabular. Check yours.

Figures in a table: proportional vs tabular
ItemQtyAmount
Hosting1₹1,111.00
Domains11₹9,980.50
Fonts4₹0.00
Design tools12₹14,400.00
Total₹25,491.50
Without: proportional figures, left-aligned. Decimal points wander; you can’t compare magnitudes at a glance.

Numbers in tables: the rules

  • Right-align numeric columns (and their headers), so units, tens and hundreds stack. Left-align text columns.
  • Use the same number of decimal places down a column.
  • Use tabular lining figures. Consider a slightly smaller size or muted colour for units and currency symbols.
  • Format by locale. In India, ₹1,12,500 (lakh grouping); elsewhere 112,500 or 112 500 or 112.500. Use Intl.NumberFormat (web) or the platform’s formatters rather than hand-rolled commas.
  • Use the minus sign (−) for negatives so they align with the plus sign and look like maths.

For a full treatment of tables and charts, see Information & Data.

Small caps, fractions and other features

OpenType features are switches inside a font. The ones worth knowing, with their CSS:

FeatureCSSUse it for
Tabular figures (tnum)font-variant-numeric: tabular-numsTables, timers, counters
Old-style figures (onum)font-variant-numeric: oldstyle-numsNumbers within long prose in serif text
Slashed zero (zero)font-variant-numeric: slashed-zeroCodes, IDs, data where 0 vs O matters
Fractions (frac)font-variant-numeric: diagonal-fractionsRecipes, measurements (1/2 → ½)
Small caps (smcp, c2sc)font-variant-caps: small-caps / all-small-capsAcronyms in prose (NASA, PDF), quiet labels
Ligatures (liga, dlig)font-variant-ligaturesStandard ligatures on by default; discretionary ones rarely
Stylistic sets (ss01…), character variants (cv01…)font-feature-settings: "ss01"Alternate glyphs, for example Inter’s alternate digits or single-storey a

True small caps are drawn letters at about x-height with weights that match lowercase. Fake small caps, which browsers synthesize by shrinking capitals when the font lacks them, look thin and pale. If your font lacks smcp, don’t use small caps; use tracked caps at a small size instead (Chapter 14).

Don't

The report was sent as a PDF to NASA and the WHO in 1997.

Full caps acronyms and lining figures in prose. They jump out of the line like shouting.
Do

The report was sent as a PDF to NASA and the WHO in 1997.

Small caps and old-style figures. Acronyms and numbers sit within the texture of the paragraph. (Small caps from Source Serif; the old-style year from Georgia, where installed.)
Key idea

Tabular for things that line up or change; proportional or old-style for things that sit in sentences.

For the solo creator

Add a utility class today: .num{font-variant-numeric:tabular-nums lining-nums}, and put it on every price, count, timer, table cell and chart label. It is the single highest-value line of CSS in this chapter. In SwiftUI, .monospacedDigit() does the same.

Do

  • Use tabular figures in tables, timers and anything that updates.
  • Right-align numeric columns and format by locale.
  • Check which OpenType features your font actually has.

Don't

  • Let a live counter jiggle with proportional figures.
  • Use browser-faked small caps or bold.
  • Hand-format numbers with string concatenation.

In the wild

  • Apple Clock & StopwatchiOS
    The stopwatch uses fixed-width digits so the running time doesn’t shift left and right every hundredth of a second. Anything that ticks needs tabular figures.
  • InterRasmus Andersson
    Documents features like tnum, zero (slashed zero), case-sensitive forms and several character variants, so product teams can tune numbers and ambiguous glyphs without changing fonts. Read your font’s feature list; it’s free capability.
  • Financial appsZerodha Kite, Robinhood and others
    Price lists and order books rely on aligned figures and right alignment so users can scan changes quickly. In data-heavy products, figure style is a usability feature.

Common mistakes

Jiggling counters

The default figures are proportional and nobody tested a live update.

Apply tabular figures to every number that changes on screen.

Feature set on a font that lacks it

The CSS is right, but the loaded font (or subset) doesn’t contain the feature.

Check the font’s features (many foundry pages list them; tools like Wakamai Fondue show them) and keep features when subsetting.

Check yourself

Your pomodoro timer shows 24:59 counting down, and users say it “shakes”. What fixes it?

Exercise 13.1 35 minutes · on your own product

The number audit

  1. List every place your product shows numbers: tables, prices, counters, dates, timers, charts.
  2. For each, decide the figure style (tabular lining for data and changing values; default for prose).
  3. Add a .num utility (or platform equivalent) and apply it. Right-align numeric columns and switch formatting to locale-aware APIs.
  4. Record a short screen capture of any live number before and after.
You're done when: every changing or tabulated number uses tabular figures, numeric columns are right-aligned, and numbers are formatted by locale.
BeginnerCompetentStrong
Tabular figures on one table.All numeric contexts covered; locale formatting in place.Also uses minus signs, consistent decimals, muted units, and checked the font’s feature support.
14

Tracking, kerning, optical sizes and variable fonts

Taught by Matthew Carter, with Erik Spiekermann and Tobias Frere-Jones

Fonts are spaced for lowercase text at one size range; capitals, very small text and very large text all need spacing adjustments, and optical sizes and variable fonts let the font itself adapt.

A type designer spends as long on spacing as on shapes. The spacing is tuned for lowercase text around reading sizes. Move away from that sweet spot and the spacing stops fitting. Two adjustments fix it: tracking (uniform letter-spacing across a run of text, letter-spacing in CSS) and kerning (adjustments between specific pairs like “AV” or “To”, built into the font and on by default in browsers).

The three tracking rules

  1. All caps and small caps: add tracking. Capitals are designed to sit next to lowercase, so in a row of capitals they crowd. Butterick suggests 5–12% extra; in CSS, letter-spacing: 0.05em to 0.12em. The smaller the caps, the more they need.
  2. Large display text: reduce tracking slightly. At 40px and above, default spacing looks loose. Try −0.01em to −0.03em. Never so tight that letters touch.
  3. Small text: add a touch. Below about 13px, a hair of extra spacing (0.01–0.02em) helps letters stay distinct. Apple’s SF does this automatically by size.

Never track lowercase body text for “style”: it breaks up word shapes and slows reading. And note a CSS detail: when you add letter-spacing, browsers turn off optional ligatures, which is what you want for spaced caps.

Lab: tracking for all caps

Account settings · Billing

Account settings · Billing (sentence case, default spacing)

Tracking: 0.00em
At 13px with 0% tracking, the caps look cramped. Slide tracking to 8–10% and they open up into a calm label. Now raise the size to 36px: the same tracking looks too loose, and 2–4% is enough. Tracking needs scale with size in the opposite direction.
Don't
RECENT TRANSACTIONS your balance is low Cramped caps; spaced lowercase
Exactly backwards. Caps crowded, lowercase spaced apart.
Do
RECENT TRANSACTIONS Your balance is low. +8% on caps; lowercase untouched
Spacing where it’s needed. Caps breathe; lowercase keeps the designer’s spacing.

Optical sizes

In metal type, each size was cut separately: small sizes had larger x-heights, sturdier hairlines, looser spacing; large sizes were finer and tighter. Digital fonts lost that when one outline was scaled to every size. Optical sizes bring it back. Some families ship separate cuts (SF Pro Text and SF Pro Display; Inter and Inter Display), and variable fonts can have an opsz axis that the browser sets automatically from the font size (font-optical-sizing: auto, the default). This page’s body text, Source Serif 4, has an opsz axis: the headings and body you are reading are slightly different designs.

opsz 8 (caption design), set at 44px Typography opsz 60 (display design), set at 44px Typography sturdier, wider, looser: built to survive small finer contrast, tighter: built to look elegant big
Same font, same size, two designs. Forcing the small optical size onto a big heading exaggerates the difference so you can see it. Normally the browser picks the right one automatically. (If fonts are blocked, both lines look identical.)

Variable fonts

A variable font is one file containing a continuous design space along axes. The registered axes are weight (wght), width (wdth), optical size (opsz), italic (ital) and slant (slnt); fonts may add custom ones, such as grade (GRAD), which changes weight without changing width. For a product this means: one file instead of six, any weight you like (550 if 500 is too light and 600 too heavy), automatic optical sizing, and tricks like adjusting grade in dark mode (Chapter 18). Use font-weight, font-stretch and font-optical-sizing when possible; drop to font-variation-settings only for custom axes.

wght axis: one file, every weight a a a a a 300400500600700 550
Continuous axes. Static fonts give you named stops; variable fonts let you choose the point between them. Use this sparingly: a system still needs few, named weights.
Key idea

Caps need air, big text needs less, small text a touch more. Let optical sizes do the rest.

For the solo creator

Put tracking into your text style tokens, never into components: --label-caps: 600 0.75rem/1.3 var(--sans); letter-spacing: .08em, display headings −0.02em, everything else 0. Then nobody (including future you) tracks lowercase body text on a whim.

Do

  • Track all-caps labels 5–12%.
  • Tighten large display headings slightly.
  • Prefer variable fonts with an opsz axis for products with wide size ranges.

Don't

  • Track lowercase body text.
  • Turn off kerning (it’s on by default; leave it).
  • Use one weight of a display cut for small UI text.

In the wild

  • SF ProApple, 2015 onward
    Apple’s system applies size-specific tracking and switches optical designs (Text below about 20pt, Display above), so developers rarely touch letter-spacing. The best tracking is the kind the system does for you.
  • Inter 42023
    Added an optical-size axis and Inter Display, so headings get tighter, finer forms automatically. Open-source fonts now offer what used to need premium families.
  • Roboto FlexGoogle, 2022
    A variable font with many axes including weight, width, optical size and grade. Grade lets you change weight for contrast without reflowing text.

Common mistakes

Tight caps buttons

Text-transform: uppercase was added without tracking.

Whenever you uppercase, add letter-spacing in the same rule.

Negative tracking on body text

It made a marketing headline look sleek, and the token leaked into body styles.

Scope negative tracking to sizes above about 24px only.

Check yourself

Your 11px uppercase section labels look cramped and dark, but your 48px hero headline looks loose. Which settings fit?

Connect the ideas · Part four recap

A countdown banner reads "SALE ENDS IN 2:09:45 -- don't miss it!" in tight caps. Which combination of fixes from Chapters 12–14 applies?

Exercise 14.1 30 minutes · on your own product

Tracking tokens

  1. Find every uppercase text in your product (search for uppercase or caps in strings).
  2. Set tracking per size using the lab: small caps around 0.08–0.1em, larger caps around 0.04em.
  3. Find headings above 32px and try −0.01 to −0.02em; compare side by side.
  4. Move all letter-spacing values into text style tokens.
You're done when: no component sets letter-spacing directly, and every caps style has tracking in its token.
BeginnerCompetentStrong
Caps tracked.Tracking tokenized by size; display headings tightened.Also adopted a variable font or optical size where available and checked results on Windows.
Part five

Type in the product

Everything so far applies to any text. Products add hard conditions: tiny labels, live numbers, names of unknown length, users who set their text to 200%, Windows laptops, slow networks, Hindi and English on one screen, code, dark mode. This Part makes your type robust, and ends with a full worked example.

15

UI typography: labels, buttons, truncation and user font sizes

Taught by Apple’s Human Interface Guidelines, with Material Design and Loren Brichter

Interface text is short, functional and unpredictable in length; design it to be scannable at small sizes, to wrap or truncate gracefully, and to grow when the user asks for bigger text.

Reading typography optimizes a paragraph you control. UI typography handles hundreds of tiny strings you don’t: a user’s name that might be “Li” or “Venkatanarasimharajuvaripeta”, a translated button label 40% longer than English, a price with seven digits, a user who has set their phone to the largest text size. The craft here is less about beauty and more about resilience.

Labels, buttons and captions

  • Labels sit close to what they label (proximity), in a quieter style than the value: smaller or muted, rarely both. Sentence case reads fastest.
  • Buttons use a verb, sentence or title case, and medium or semibold weight at body size or slightly smaller. Keep the label visually centred (mind the invisible line box from Chapter 10) and give it padding in em so it grows with text.
  • Captions and helper text are the smallest size in your scale, but not below 12px on the web (Apple’s smallest style is 11pt) and with enough contrast to read.
  • Numbers in UI are often the most important element on a screen (a balance, a count, a temperature). Let them be the largest text, in tabular figures, with units smaller and muted.
STORAGE USED 12.4 GB of 50 GB Photos take up most of your space. Manage storage 1 · Overline: tracked caps, muted 2 · The number leads, tabular 3 · Units smaller and muted 4 · Helper: smallest size, AA contrast 5 · Button: verb, semibold, em padding
A card is a tiny type system. Five roles, two weights, two colours, three sizes.

Wrapping vs truncation

When text is longer than its space, you have three options: wrap it, truncate it, or let it overflow (never). The default should be wrap: it keeps all the information and adapts to translations and large text. Truncate only where a fixed height matters for scanning (list rows, tabs, table cells), and then:

  • Truncate at the end for titles and names (“Quarterly planning for the…”), using an ellipsis, and give the full text on hover, focus, or the detail view.
  • Truncate in the middle for file names and paths, where the end carries meaning (“Invoice_2026…final_v3.pdf”), as macOS Finder does.
  • Clamp multi-line previews (-webkit-line-clamp / line-clamp) to two or three lines, not one.
  • Never truncate numbers, prices, dates or anything a user must compare or act on.
Don't
Invoice_Acme_Studio_March_2026_final_v3.pdf
Invoice_Acme_Studio_March_2026_final_v2.pdf
End truncation on files. v2 and v3 look identical.
Do
Invoice_Acme…final_v3.pdf
Invoice_Acme…final_v2.pdf
Middle truncation. The distinguishing end survives.
Do
Quarterly planning for the new pricing experiment
Wraps to two lines; nothing hidden
Wrap by default. Let rows grow when the content is the point.

Dynamic Type and user font sizes

Many people enlarge text: on iOS through Dynamic Type (from the default “Large”, where Body is 17pt, up through accessibility sizes where Body reaches about 53pt), on Android with the font scale setting, on the web with browser zoom and default font size. WCAG requires that text can be resized to 200% without loss of content or function. Your layout must survive. That means: sizes in relative units (rem on the web, text styles on native), no fixed heights on text containers, buttons that grow, rows that wrap, and layouts that switch from horizontal to vertical when text gets big (iOS apps commonly stack label and value at accessibility sizes).

Lab: user text size

Fixed layout (heights in px, nowrap)

NotificationsDaily summary
Default currencyIndian rupee (₹)
BackupWeekly
Save changes

Flexible layout (rem, min-height, wrap)

NotificationsDaily summary
Default currencyIndian rupee (₹)
BackupWeekly
Save changes
Drag to 200%. The fixed layout clips labels and the button text; the flexible one grows rows and wraps values under labels. Real users run their phones at these sizes every day.

Minimum sizes

Practical floors: 16px for body text and form inputs on the web (iOS Safari zooms the page when focusing an input under 16px, which annoys users), 12–13px for secondary UI text, 11pt as Apple’s smallest system style. Below those, use them only for non-essential, decorative or legal-fine-print text, and even then, with sufficient contrast.

For the solo creator

Twice a month, set your phone to the largest accessibility text size and your browser to 200% zoom, and use your product for five minutes. You will find clipped buttons and overlapping labels within seconds. Fix them before users write in. It’s the cheapest usability test there is.

Do

  • Wrap by default; truncate deliberately with an escape.
  • Use relative units and text styles that scale with user settings.
  • Make inputs at least 16px on mobile web.

Don't

  • Fix heights on anything containing text.
  • Truncate numbers, prices or dates.
  • Set labels in px on native platforms that offer text styles.

In the wild

  • iOS SettingsApple
    At accessibility text sizes, rows stack the label above the value and grow vertically rather than truncating. The layout itself changes shape as type grows.
  • macOS FinderApple
    Truncates long file names in the middle, keeping the start and the extension visible. Truncate where the information isn’t.
  • TweetieLoren Brichter, 2008
    Set tweet text, names and metadata with clear weight and colour steps in fast-scrolling rows, a pattern most timeline apps followed. Scannable rows come from consistent roles, not decoration.

Common mistakes

Designing only with short English strings

Mock data is “John Doe” and “Save”.

Test with long names, German or Tamil translations, seven-digit numbers and 200% text. Keep these as fixtures.

Truncation with no way to see the full text

The ellipsis fixed the layout, so the job felt done.

Provide a tooltip on hover/focus, an expanded detail view, or a wrap on tap.

15px inputs on mobile web

It matched the design’s label size.

Use 16px or more for input text, or users get an unexpected zoom on focus in iOS Safari.

Check yourself

In a document list, titles are often long and many share the same beginning (“Meeting notes – Monday”, “Meeting notes – Tuesday”). Rows must stay one line. What should you do?

Exercise 15.1 45 minutes · on your own product

The stress fixtures

  1. Create test data: a 40-character name, a 1-character name, a ₹12,34,56,789.00 amount, a translated label 40% longer, and an emoji in a title.
  2. Load it into your three busiest screens.
  3. Run them at 100%, 150% and 200% text size (or browser zoom).
  4. Fix every clip, overlap and unwanted truncation; decide deliberately where to wrap or truncate.
You're done when: your three screens survive the fixtures at 200% with no clipped or overlapping text, and the fixtures are saved for future testing.
BeginnerCompetentStrong
Fixtures created; issues listed.Issues fixed with wrapping, relative units and min-heights.Layouts adapt structurally at large sizes (stacking), and fixtures are part of your regular test routine.
16

Rendering and loading

Taught by Matthew Carter (on screen fonts), with web performance practice

The same font looks different on macOS, Windows and Android, and it may arrive late or not at all; test on real platforms and load fonts so text is readable immediately and doesn’t jump when the font arrives.

Why your font looks different on Windows

Text rendering turns ideal outlines into pixels, and platforms make different trade-offs. macOS has long favoured fidelity to the outline shape, which looks smooth and slightly heavier and blurrier; since macOS Mojave (2018) it no longer uses subpixel antialiasing by default, so text on non-Retina Mac screens looks lighter than it used to. Windows, with ClearType and DirectWrite, has favoured snapping strokes to the pixel grid for sharpness, which relies more on hinting (instructions in the font that tell the rasterizer how to fit the grid). A font with poor hinting can look crisp on a Mac and ragged or thin on a Windows laptop. On high-density screens (2x and above) these differences shrink a lot; on the 1x office monitors many people still use, they matter.

A 1.3px stem between pixels Smooth (outline-faithful): two grey columns, soft Grid-fitted (hinted): one crisp column, slightly moved Neither is wrong; they are different trade-offs. Test your font on both.
Pixels are coarse. At body sizes a stem is one or two pixels wide; how the system rounds it changes the weight and sharpness of the whole paragraph.

A CSS note: -webkit-font-smoothing: antialiased only affects macOS browsers, making text look lighter. Many sites set it globally; it can help light text on dark backgrounds, but on a light background it often makes body text too thin. Use it deliberately, not by habit.

Font loading: FOIT, FOUT and layout shift

Web fonts download after the page starts rendering. Browsers then choose between two failure modes. FOIT (flash of invisible text): text is hidden until the font arrives, typically for up to about three seconds, and on a slow connection users stare at a blank page. FOUT (flash of unstyled text): text shows in a fallback font immediately and swaps when the web font loads, which may shift the layout. You control this with font-display in @font-face:

ValueBehaviourUse it for
swapFallback immediately, swap whenever the font arrivesBody text, most cases
optionalVery short wait; if the font isn’t ready, use fallback for this page viewWhen stability matters more than the exact font; repeat visits get it from cache
fallbackShort invisible period, short swap window, then stick with fallbackA compromise
blockInvisible until loaded (up to a timeout)Icon fonts only, where a fallback would show nonsense
0 sfont arrives (1.8 s)3 s block (FOIT) invisible text web font swap (FOUT) fallback web font · layout jumps swap + matched fallback adjusted fallback web font · no jump
Show text immediately, and make the swap invisible. Metric overrides on the fallback font make it occupy the same space as the web font.

A loading recipe

  1. Self-host WOFF2 files from your own domain (fast, private, no third-party dependency).
  2. Subset to the characters and scripts you need (with unicode-range so other scripts load only on demand), but keep the OpenType features you use.
  3. Use one variable file instead of many static weights where you can.
  4. Preload the one or two files needed above the fold: <link rel="preload" as="font" type="font/woff2" crossorigin>.
  5. Set font-display: swap (or optional) and define a fallback @font-face that uses a local font with size-adjust, ascent-override and descent-override so its metrics match. Several frameworks (for example Next.js’s font tooling) generate these for you.
For the solo creator

The system font stack has zero loading cost, zero layout shift and zero licence risk. If you choose a web font, budget one afternoon to do the recipe properly once, put it in your project template, and never think about it again. Test with your browser’s network throttling set to “Slow 4G”.

Do

  • Test on a Windows machine and a 1x screen, not only on a Retina Mac.
  • Self-host, subset, preload and use swap or optional.
  • Match fallback metrics to avoid layout shift.

Don't

  • Hide text while fonts load.
  • Ship nine static weights “just in case”.
  • Set -webkit-font-smoothing: antialiased globally without checking light mode body text.

In the wild

  • Verdana & GeorgiaMatthew Carter and Tom Rickner, 1996
    Drawn with the pixel grid in mind and extensively hand-hinted, they stayed crisp on low-resolution Windows screens for decades. Rendering is part of type design.
  • Google Fonts APIfont-display parameter
    The CSS API accepts display=swap (as this page uses) and serves subsetted WOFF2 files split by unicode-range. Even if you self-host, copy its subsetting strategy.
  • Next.js next/fontVercel
    Self-hosts fonts at build time and generates a size-adjusted fallback to reduce layout shift. Framework tooling can automate the hard part of loading.

Common mistakes

Only testing on a Retina Mac

It is the machine you own.

Borrow or buy a cheap Windows laptop or use a cloud browser testing service; check your smallest text and thin weights.

Layout jump on load

Fallback and web font have different widths and heights.

Choose a fallback with similar proportions and tune it with metric overrides; measure with Lighthouse’s CLS score.

Check yourself

Your landing page shows blank space for about 2 seconds on mobile networks, then text pops in. What change helps most?

Exercise 16.1 60 minutes · on your own product

Loading and rendering check

  1. Open your product with network throttling (Slow 4G) and cache disabled. Record what text does in the first three seconds.
  2. List your font files, sizes and formats. Remove unused weights; convert to WOFF2; subset if appropriate.
  3. Apply the five-step recipe.
  4. Open your product on a Windows machine (or a cloud test) and screenshot body text, small labels and a thin weight.
You're done when: text appears immediately on a slow connection, total font weight is noted before and after, and you have Windows screenshots with any fixes made.
BeginnerCompetentStrong
font-display set.Self-hosted, subset, preloaded; font bytes reduced.No measurable layout shift from fonts, verified on Windows and a 1x screen.
17

Many scripts: Devanagari, mixed text and localization

Taught by Indian Type Foundry and Ek Type (Indic type design), with Google’s Noto project

Other scripts have different shapes, heights and rules; give them fonts designed for them, enough line height for their marks, and sizes matched by eye to your Latin text.

If your product might be used in India, Hindi, Marathi, Bengali, Tamil, Telugu and other Indian languages are not an edge case. Even an English-first app shows Indian names, addresses and user-generated text. The Latin rules in this guide don’t transfer automatically. Devanagari, used for Hindi, Marathi, Nepali and Sanskrit, is a good example of why.

How Devanagari differs

  • The headline (shirorekha). Most letters hang from a horizontal line at the top, which joins letters into words. Visually, the “x-height” is the body between the headline and the baseline.
  • Marks above and below. Vowel signs (matras) and other marks sit above the headline and below the baseline, and conjuncts stack. That needs more vertical room than Latin: line-height around 1.6–1.8 for body text, versus 1.4–1.6 for Latin.
  • Apparent size. At the same font-size, Devanagari often looks smaller than Latin because the main body is a smaller fraction of the em. It commonly needs a slightly larger size (often 10–15% more) to feel equal.
  • Shaping. Letters change form in combination (conjuncts, reordering of vowel signs). This requires proper OpenType shaping, which modern browsers and OSes do, but which breaks if you letter-space, fake bold or cut strings in the middle of a grapheme cluster.
  • No case. There are no capitals, so all-caps styling and tracking rules don’t apply; use weight and size for hierarchy.
टाइपोग्राफ़ी Type marks above headline (shirorekha) baseline marks and conjuncts below Guides are approximate; they vary by font. Give Devanagari more line height than Latin.
More vertical territory. Marks above the headline and below the baseline make tight Latin line-heights collide in Devanagari.
Don't

आपका ऑर्डर भेज दिया गया है। डिलीवरी की स्थिति आप ऑर्डर पेज पर देख सकते हैं, और पते में कोई गलती हो तो हमसे संपर्क करें।

Latin settings applied. 15px at line-height 1.2: marks crowd the line above.
Do

आपका ऑर्डर भेज दिया गया है। डिलीवरी की स्थिति आप ऑर्डर पेज पर देख सकते हैं, और पते में कोई गलती हो तो हमसे संपर्क करें।

Script-specific settings. 17px, line-height 1.75, in a Devanagari font: calm and readable.

The Hindi sample reads: “Your order has been sent. You can see the delivery status on the order page, and contact us if there is a mistake in the address.”

Fonts for Indian scripts

Use a font designed for the script, not whatever the system falls back to. Good free options: the Noto families (Noto Sans Devanagari, Noto Serif Devanagari, and Noto for Bengali, Tamil, Telugu, Kannada, Malayalam, Gujarati, Gurmukhi and Odia), which aim at broad, consistent coverage; Hind and other families from Indian Type Foundry; Mukta from Ek Type; and IBM Plex Sans Devanagari, which matches IBM Plex Sans. Many of these were designed alongside a Latin companion, so the two scripts sit together well.

Mixed scripts on one screen

When a user’s Hindi name appears in an English UI, or an English brand name appears in Hindi text, two fonts share a line. Make it work by: listing a script-specific font in the stack (CSS picks per character, so font-family: Inter, "Noto Sans Devanagari", sans-serif uses Inter for Latin and Noto for Devanagari); setting lang attributes on content in other languages (this drives font selection, hyphenation and screen reader pronunciation); sizing so both scripts look the same size; and setting line-height for the taller script wherever it might appear.

Localization beyond Indian scripts

  • Expansion: translated strings are often 30% longer or more (German, Finnish); short English labels can double. Wrap, don’t clip (Chapter 15).
  • CJK: Chinese, Japanese and Korean text has no word spaces, wraps between most characters, needs larger fonts (fonts are big files; rely on system fonts or careful subsetting), and has its own punctuation rules. WCAG’s line-length guidance is 40 characters for CJK versus 80 for Latin.
  • Right-to-left: Arabic and Hebrew mirror layouts; use logical CSS properties (margin-inline-start, text-align: start) so your layout flips correctly.
  • Numerals and formatting: dates, numbers and currency vary by locale; always use locale-aware formatters.
For the solo creator

Even if you only ship English, add a Devanagari font to your fallback stack and set line-heights that won’t crush Indian names in user content. If you localize, start with one Indian language and test with a native reader; a single ten-minute session will teach you more than any rule.

Do

  • Use fonts designed for each script you support.
  • Give Devanagari and other Indic scripts more line height and slightly larger size.
  • Mark languages with lang and use logical CSS properties.

Don't

  • Letter-space or fake-bold complex scripts.
  • Truncate strings by character count (you may cut a cluster in half).
  • Assume Latin metrics and spacing work for every script.

In the wild

  • NotoGoogle
    A project to cover all scripts in Unicode with harmonized designs, named for avoiding “tofu” (the empty boxes shown for missing glyphs). Coverage is a typographic responsibility.
  • Indian Type Foundry & Ek TypeIndia
    Released many free, multi-script families (Hind, Mukta and others) through Google Fonts, designed by people who read the scripts daily. Prefer fonts made by native readers of the script.
  • Government and banking apps in IndiaUPI era
    Many offer Hindi and regional-language interfaces, where tight Latin-style line-heights are a common source of clipped matras. Test vertical clipping in every script you ship.

Common mistakes

Clipped matras

Fixed-height containers or overflow: hidden with Latin line-heights cut off marks above and below.

Use script-aware line-heights and avoid clipping text containers vertically.

Missing glyphs (tofu)

The web font covers only Latin and there’s no fallback for other scripts.

Add script fonts to the stack and test with real names and content.

Check yourself

Your English app shows user names in list rows at 15px with line-height 1.25 and overflow hidden. Hindi names look cut off at the top. What is the best fix?

Exercise 17.1 40 minutes · on your own product

The script stress test

  1. Insert Hindi (and if relevant Tamil or Bengali) names and a paragraph of Hindi into your product’s content (names, notes, titles).
  2. Check: correct font, no tofu, no clipped marks, comparable apparent size, comfortable line-height.
  3. Fix the font stack, line-heights and any clipping.
You're done when: mixed-script content renders correctly in your three main screens, with screenshots before and after.
BeginnerCompetentStrong
Issues found.Font stack and line-heights fixed; no clipping.Sizes matched by eye across scripts, lang attributes set, and a native reader confirmed it reads naturally.
18

Monospace, code and type in dark mode

Taught by Oliver Reichenstein, with Matthew Butterick

Code needs a monospace with unmistakable characters set slightly smaller than body text; dark mode needs slightly lighter weights and softer contrast, because light text on dark looks bolder and glows.

Choosing a code font

In code, every character carries meaning and readers scan vertically for alignment, so monospace (every glyph the same width) is the norm. What separates a good code font: distinct 0 O, 1 l I, and { } ( ) [ ]; punctuation big enough to see (a comma vs a full stop matters); a generous x-height; and enough weight to survive dark themes. Good choices include SF Mono and Menlo (Apple), Consolas and Cascadia Code (Microsoft), JetBrains Mono, IBM Plex Mono, Fira Code and Source Code Pro. For a web stack, ui-monospace, "SF Mono", Menlo, Consolas, monospace gives a good native mono on each platform, as this course uses.

Setting code

  • Size it down. Monospace looks bigger than proportional text at the same size because it is wider. Inline code usually sits at 0.85–0.9em of the surrounding text (this page uses 0.86em).
  • Leading 1.5–1.6 for code blocks; tight code is hard to scan.
  • Don’t wrap code by default in blocks; scroll horizontally, and keep lines short in examples you write.
  • Ligatures are a choice. Programming ligatures (Fira Code, JetBrains Mono, Cascadia Code) turn != or => into single symbols. Some developers love them; Butterick argued against them in an essay because they can misrepresent the actual characters. In a product that shows code to others, leave them off; in an editor, make them a setting.
Don't

const total = items.filter(i => i.qty > 0).reduce((s, i) => s + i.price * i.qty, 0);
if (total != 0) { log("Total: " + total); }

Code in a proportional serif. No alignment, punctuation lost, wraps mid-expression.
Do
const total = items
  .filter(i => i.qty > 0)
  .reduce((s, i) => s + i.price * i.qty, 0);
if (total !== 0) log(`Total: ${total}`);
A real code font, slightly smaller, generous leading. Structure is visible; punctuation is clear.

Monospace for writing

iA Writer made a deliberate, debated choice: a monospace-derived face for prose writing. The argument is that monospace slows the eye slightly and makes the text feel like a draft, which encourages writing rather than admiring. iA later designed Duo (a few wide letters like m and w get extra width) and Quattro (closer to proportional) to keep that “draft” feel while reducing monospace’s gappy texture. The lesson for your product isn’t “use monospace”; it is that a font’s texture changes how people feel about the act they perform. Choose texture for the job.

Type in dark mode

Light text on a dark background looks heavier and slightly blurred than the same text dark-on-light. Part of this is perceptual (bright areas appear to spread into dark ones, an effect often called irradiation), part is rendering, and for people with astigmatism very bright text on black can appear to glow or smear (halation). Three adjustments help:

  1. Soften the extremes. Avoid pure white (#FFF) on pure black (#000). Off-white on a very dark grey keeps contrast well above 4.5:1 while reducing glare.
  2. Lighten weight slightly. If body text is 400 in light mode, it can look like 450 in dark mode. Variable fonts with a grade axis let you reduce apparent weight without changing width; otherwise consider one step lighter for large text, and check thin weights don’t disappear.
  3. Re-check muted text. Secondary greys tuned for light mode often fail or look muddy in dark mode. Define them separately (this course defines every colour token twice).
Dark mode type: harsh vs tuned
Light mode

Regular weight, dark ink on white. The reference look your design started with.

Dark, untuned

Pure white on pure black, weights bumped “for punch”. Strokes bloom and the paragraph glows.

Without: maximum contrast and heavier weights make dark mode text look bolder and harsher than the light design.
Key idea

Dark mode isn’t inverted light mode. Type needs its own, slightly gentler settings.

For the solo creator

Make text colour and, if your font allows, weight or grade into tokens that switch with the theme. Then read one long screen in both modes, at night, at low screen brightness. Whichever mode feels heavier gets adjusted. Ten minutes, once.

Do

  • Use a code font with distinct 0/O and 1/l/I, at about 0.875em.
  • Soften dark mode contrast and lighten weights slightly.
  • Define secondary text colours separately per theme.

Don't

  • Set prose in monospace without a reason tied to the product’s job.
  • Use #FFF on #000 for long text.
  • Use thin weights in dark mode small text.

In the wild

  • iA WriterMono, Duo, Quattro
    Offers three related faces so writers can choose how “draft-like” the text feels, and publishes them under an open licence. Texture is a product decision.
  • JetBrains MonoJetBrains, 2020
    A code font with a tall x-height and distinct glyphs, designed for long reading sessions in an IDE, with optional ligatures. Code fonts are reading fonts for a specific kind of text.
  • Apple’s dark modemacOS Mojave, iOS 13
    Uses near-black and dark grey backgrounds with off-white and grey label colours, rather than pure white on pure black. Even the platform tones down contrast for comfort.

Common mistakes

Code at body size

Inline code inherits 1em and looks oversized and heavy.

Set code to about 0.85–0.9em and check line spacing isn’t pushed apart by it.

Inverted colours only

Dark mode was created by swapping black and white.

Tune text colours, weights and secondary greys separately for dark.

Check yourself

Users of your reading app say dark mode is “tiring” after 20 minutes. Text is #FFFFFF, weight 500, on #000000. What do you try first?

Exercise 18.1 30 minutes · on your own product

Two-theme type pass

  1. Screenshot one long screen in light and dark mode side by side.
  2. Squint: which looks heavier? Adjust dark text colour and weight until both feel the same.
  3. If your product shows code or IDs, check the font distinguishes 0/O and 1/l/I, and size inline code to about 0.875em.
You're done when: light and dark screenshots look like the same typography, with contrast ratios noted (both at or above 4.5:1 for body).
BeginnerCompetentStrong
Dark colours softened.Weights and secondary colours tuned per theme; code font checked.Theme-aware tokens for colour and weight/grade, verified at night on a phone at low brightness.
19

Worked example: a plain article, refined in six steps

Putting it all together, with everything from Chapters 7 to 14

Good typography is a sequence of small, ordered decisions; applied in the right order, six steps turn default text into a calm, professional page.

Below is a short article as it might appear in a product changelog or blog, first with browser-ish defaults and no decisions. Step through it. Each step applies one chapter and changes only what that chapter controls. Notice that the biggest improvements come early (size, leading, measure) and the later ones are refinements. That ordering is the practical lesson: when time is short, do steps 1 and 2 first.

1Bodysize, leading 2Measure45–75 chars 3Scaleheading sizes 4Rhythmspacing, proximity 5Hierarchymeta, labels 6Detailsquotes, wrap, figures Yellow: highest impact per minute. Do these first when time is short.
The order matters. Fix what every line depends on before polishing what a few lines show.
Lab: refine the article step by step

Engineering notes

How we cut our app's load time in half without a rewrite

Rohit Sharma · 12 March 2026 · 6 min read · 1,204 views1,204 views

For months our dashboard took 4-5 seconds4–5 seconds to show anything useful. Users called it "slow but fine"“slow but fine”, which is another way of saying they were quietly looking for alternatives.

We assumed we needed a rewrite. Instead, we measured. Three things turned out to matter: fonts that blocked rendering, a chart library loaded on every page, and an API call that waited for another one for no reason.

Start with what users see first

The fastest fix was the fonts. We had nine weights loading from a third-party server with font-display: blockfont-display: block, so text stayed invisible for up to three seconds on slow networks. We cut it to one variable file, self-hosted, with a matched fallback...… and the page started showing text almost immediately.

Step 0 · Plain: Arial 13px, line-height 1.2, full width, headings barely bigger, straight quotes. Nothing is wrong enough to be noticed; everything is slightly tiring.

What each step did, and why in this order

  1. Body (Chapter 7). A screen serif at 18px, line-height 1.6, paragraph spacing instead of nothing. Every line in the article improved at once.
  2. Measure (Chapter 7). The body column capped at about 34em, roughly 65–75 characters on desktop. Return sweeps became reliable.
  3. Scale (Chapter 8). Title and subheading set from a scale, in the sans, with tighter leading and slight negative tracking on the title.
  4. Rhythm (Chapter 10). More space above the subheading than below; title separated from the body. Sections now group visually.
  5. Hierarchy (Chapter 9). The kicker became a tracked overline; metadata became smaller, muted sans. The title is now unambiguously first.
  6. Details (Chapters 11–13). Curly quotes and apostrophe, an en dash for the range, a real ellipsis, balanced headings, pretty paragraph wrapping and tabular figures in the metadata.
Before
Dense, wide, flat
Before. A wall of grey; no entry point.
After
Clear entry, calm body
After. Title first, metadata quiet, body comfortable, sections grouped.

Checklist: type audit for your product

Choice
Setting
Details
Robustness
For the solo creator

Run this exact six-step sequence on one real screen of your product per week. The first time takes an hour; by the third time it takes fifteen minutes, because steps 1–3 become tokens you reuse, and only 4–6 need judgement per screen.

Do

  • Fix body size, leading and measure before anything else.
  • Change one thing per step and look again.
  • Keep a before screenshot; the difference motivates.

Don't

  • Start with the font or the details.
  • Change five settings at once and lose track of what helped.
  • Stop at step 2 for headings-heavy screens; hierarchy matters there.

In the wild

  • Reader modesSafari, Firefox, Edge
    Apply roughly steps 1–4 automatically to any page: a readable size, generous leading, a narrow column, and clean spacing. The first four steps are so valuable browsers ship them as a feature.
  • Ghost & SubstackPublishing platforms
    Default article templates already have a comfortable body size, measure and heading scale, which is a large part of why writers choose them. Good defaults are a product advantage.
  • MediumEarly 2010s
    Built its reputation partly on how good plain text looked by default: large serif body, narrow column, calm metadata. Typography can be the product’s first impression.

Common mistakes

Polishing details on a broken base

Curly quotes and balanced headings are satisfying, quick wins.

Do them, but only after body size, leading and measure are right.

Refining one page, not the system

The article looks great; the settings live in that page’s CSS.

Promote every decision to tokens so the next page starts at step 6.

Check yourself

You have 20 minutes before launch and your blog template is untouched defaults. Which two steps do you do?

Exercise 19.1 90 minutes · on your own product

Six steps on your longest screen

  1. Pick the screen with the most text in your product. Screenshot it as step 0.
  2. Apply steps 1 to 6 in order, screenshotting after each.
  3. Arrange the seven screenshots in a row and write one sentence under each about what changed and how it felt.
  4. Promote every setting you changed into a token or text style.
You're done when: you have a seven-frame strip and the settings live in your design tokens, not the screen.
BeginnerCompetentStrong
Steps applied with some skipped.All six applied in order, with notes.Tokens updated and the improvement carried to at least two other screens with no extra per-screen work.

Wrap-up

Ten things to remember

  1. Type is most of your interface; type settings are the highest-leverage, most global design decisions you make.
  2. X-height, aperture, contrast and spacing predict how a face behaves on screens. Judge faces by these, not by their specimen.
  3. Legibility is the face; readability is the setting. Most problems are settings, and settings are free to fix.
  4. Start with the system font; leave it only for a reason you can name. One family is usually enough.
  5. Body 16–20px, line-height 1.4–1.6, 45–75 characters per line, tuned together.
  6. Five to seven named sizes from a gentle scale; weight, colour and space for the minor levels.
  7. More space above headings than below; spacing from tokens on one base unit.
  8. Ragged right by default; balance headings; justify only with hyphenation and width.
  9. Curly quotes, real dashes and ellipses in prose; tabular figures for data; tracked caps; straight characters in code.
  10. Make type robust: user text sizes, long strings, Windows rendering, slow fonts, Indian scripts and dark mode.

Self-assessment: I can…

Practice assignment for the next two weeks

Typography improves with daily looking and weekly doing. Spend about 20 minutes a day.

  1. Days 1–3: See. Each day, screenshot one screen from an app you admire and one you don’t. Annotate size, leading, measure, scale steps, weights and one detail (quotes, figures, tracking). Use this guide’s vocabulary.
  2. Days 4–5: Decide. Write your type decision record (Exercise 5.1) and set body tokens (Exercise 7.1).
  3. Days 6–8: Systematize. Collapse your sizes into a named scale (8.1), fix spacing (10.1) and hierarchy (9.1).
  4. Days 9–10: Detail. Punctuation sweep (12.1), number audit (13.1), tracking tokens (14.1).
  5. Days 11–13: Harden. Stress fixtures at 200% (15.1), loading and Windows check (16.1), script test (17.1), dark mode pass (18.1).
  6. Day 14: Show. Run the six-step worked example on your longest screen (19.1), complete the type audit checklist, and put a before/after strip somewhere you’ll see it.

Reading list

  • The Elements of Typographic Style
    Robert Bringhurst (1992, later editions) · The classic on text typography: measure, rhythm, scale, details. Print-oriented but the principles transfer.
  • Butterick’s Practical Typography
    Matthew Butterick (free online) · Blunt, practical rules with numbers; the fastest way to fix everyday text. Read the summary page first.
  • Stop Stealing Sheep & Find Out How Type Works
    Erik Spiekermann and E. M. Ginger · A friendly, visual introduction to seeing and choosing type.
  • Thinking with Type
    Ellen Lupton · Letter, text, grid, with many visual examples; good for building vocabulary.
  • On Web Typography
    Jason Santa Maria (A Book Apart, 2014) · Choosing and pairing type for screens, with a designer’s eye.
  • Web Typography
    Richard Rutter (2017) · Detailed, technical guide to setting type with CSS, from measure to OpenType features.
  • “Web Design is 95% Typography”
    Oliver Reichenstein, Information Architects (2006) · The short essay that frames this whole guide.
  • “The Crystal Goblet”
    Beatrice Warde (1930 lecture) · Why type in the service of reading should be invisible.
  • “The Science of Word Recognition”
    Kevin Larson, Microsoft (2004) · The readable research review behind Chapter 4’s word-shape discussion.
  • “More Meaningful Typography”
    Tim Brown, A List Apart (2011) · The article that brought modular scales to web design.
  • Typeface Mechanics series
    Tobias Frere-Jones (essays on his studio’s site) · How type designers solve overshoot, spacing and other optical problems.
  • Apple Human Interface Guidelines: Typography, and Material Design 3: Typography
    Apple; Google · The platform rules for text styles, sizes and dynamic type you’ll build against.

Next, Reading & Writing applies everything here to calm tools for long-form reading and focused writing, and Accessible & Inclusive goes deeper on contrast and text scaling.