Skip to content
Strynal, Digital Agency

Design 9 min read

Typography for the Web: Building a Type System

A practitioner's guide to web typography: modular scale, measure, vertical rhythm, variable fonts, font-loading, and accessibility, with practical defaults.

By Strynal Team

Most sites do not have a typography problem. They have a no-system problem. Web typography fails when every heading picks its own size, every paragraph guesses its own line height, and nobody can say why a number was chosen. A type system replaces that guesswork with a small set of decisions you make once and reuse everywhere. It is the cheapest way to make a site feel considered.

This is a build guide, not a font-pairing mood board. We cover the scale, the measure, the rhythm, the fonts, how they load, and how to keep all of it accessible, with practical defaults where they help.

Why web typography needs a system

A page is mostly type. Strip the imagery and the color and what’s left is text doing the work: reading order, hierarchy, emphasis, rest. When the type is arbitrary, the page reads as arbitrary, even when each choice looked fine in isolation.

A system fixes this by constraining the choices. Instead of “what size should this heading be,” you ask “which step on the scale.” Instead of “what line height feels right,” you reach for a ratio tied to the font size. A few rules generate a consistent surface across hundreds of pages, and a new contributor can extend it without inventing values.

A type system is not a list of font sizes. It is a set of rules that make the next font size obvious.

This is the same logic behind any design system for a lean team: pay a small structuring cost once so every downstream decision gets cheaper. Typography is the highest-leverage place to start, because it touches every screen.

The modular scale

Start with the sizes. A modular scale is a sequence of font sizes generated by multiplying a base size by a ratio, step after step. Pick a base (1rem, or 16px, is a sound default for body text) and a ratio, and the scale produces the rest.

The ratio sets the personality. A small ratio like 1.125 (major second) keeps headings close to body text: calm, editorial, good for text-dense interfaces. A large ratio like 1.333 (perfect fourth) or 1.5 produces dramatic jumps: confident and marketing-forward. Most product and content sites live happily between 1.2 and 1.25.

A practical default scale

Here is a usable starting point at a 1.25 ratio, rounded for sanity:

  • --text-xs: 0.8rem
  • --text-sm: 0.9rem
  • --text-base: 1rem
  • --text-lg: 1.25rem
  • --text-xl: 1.563rem
  • --text-2xl: 1.953rem
  • --text-3xl: 2.441rem
  • --text-4xl: 3.052rem

Name the steps by intent or position, not by pixel value: use --text-2xl, not --font-31. A semantic name survives a ratio change; a pixel name becomes a lie the moment you retune the scale. This is the token discipline that closes the Figma-to-production handoff gap: both sides reference the name, so the value can move in one place.

Fluid type, carefully

You can make sizes scale with the viewport using CSS clamp(), so a headline grows on a wide screen without a cascade of breakpoints. font-size: clamp(2rem, 1.5rem + 2vw, 3rem) sets a floor, a preferred fluid value, and a ceiling. Two cautions: keep the minimums readable on small screens, and make sure a fluid headline never zooms past the point where the line measure breaks. Fluidity is a tool, not a default. Apply it to display sizes and leave body text fixed.

Measure: the most ignored variable

Measure is the length of a line of text, counted in characters. It is the most underused lever in web typography, and the one that most affects whether long-form content is actually readable.

Too long and the eye loses its place returning to the next line. Too short and reading turns into a stutter of constant carriage returns. The reliable range for body copy is 45 to 75 characters per line, with roughly 66 as a comfortable target.

Set it directly. The ch unit is approximately the width of the 0 glyph, so max-width: 66ch on your text container gets you close without arithmetic. Constrain the text column, not the whole layout. A wide page with a narrow, well-measured reading column is a hallmark of typography that someone thought about.

Vertical rhythm and spacing

Vertical rhythm is the consistent vertical spacing that ties a page together: the predictable beat between lines, paragraphs, and sections. The foundation is line height, and the most common mistake is setting it once and forgetting it.

Line height should change with size. Body text wants room to breathe: a unitless line-height of about 1.5 to 1.6 keeps long copy readable. Large headings need the opposite: tight line-height of 1.05 to 1.2, because generous leading on big type opens distracting gaps. Set it as a unitless number so it scales with the element’s font size instead of inheriting a fixed pixel value.

A spacing scale, not random margins

Derive vertical spacing from a base unit and reuse it everywhere:

  • Pick a base of 0.25rem (4px) and build a scale: 4, 8, 12, 16, 24, 32, 48, 64.
  • Space paragraphs with one consistent step (often 1rem), not ad hoc margins.
  • Make section spacing a larger, equally consistent step so the page has a clear meter.
  • Let headings carry more space above than below, so each heading visually belongs to the content it introduces.

Spacing feels intentional because it is. Every gap is a step on one scale, not a number someone nudged until it looked okay.

Variable fonts and font choices

A variable font packs many weights, and sometimes width and optical size, into a single file with continuous axes. Instead of shipping separate files for regular, medium, semibold, and bold, you ship one file and request any weight along the axis: the full weight range for hierarchy without four network requests.

A few opinions that hold up in production:

  • Two families is plenty. One for headings, one for body (or one versatile family doing both). A third typeface needs to earn its place; usually it can’t.
  • Use real weights, not faux ones. If you need bold, load the bold (or a variable axis that reaches it). Letting the browser synthesize bold or italic produces muddy, off-brand letterforms.
  • Respect the optical size axis when a font has one. Display cuts for large sizes, text cuts for small: it is the difference between a headline that looks crafted and one that looks scaled.
  • Always declare a real fallback stack. A good system-font fallback (system-ui, -apple-system, "Segoe UI", Roboto, sans-serif) means the page is readable before your webfont arrives, and survives if it never does.

Restraint here is the point. A focused palette of two families and a clear weight ladder will out-design a page juggling five typefaces every time.

Font loading is a performance decision

Web fonts are render-blocking by nature: the browser has text to paint and is waiting on a file to know how. How you handle that wait decides whether visitors see your content immediately or stare at a blank space. Typography is where design and Core Web Vitals meet, and the meeting can go badly.

Two failure modes have names. FOIT (flash of invisible text) hides text until the font loads. FOUT (flash of unstyled text) shows fallback text first, then swaps. FOUT is almost always the better trade: people can read immediately, and a brief restyle beats an invisible page.

The practical toolkit:

  1. Set font-display: swap (or optional for non-critical fonts) so text renders in the fallback and swaps when the webfont arrives.
  2. Self-host and preload the critical font. <link rel="preload" as="font" crossorigin> on the one or two files above the fold starts the download early and removes a third-party connection from the critical path.
  3. Subset aggressively. Ship only the characters and weights you use. A Latin-only subset of a variable font is a fraction of the full file.
  4. Use WOFF2. It is the smallest format and universally supported now.
  5. Match the fallback’s metrics. size-adjust and the @font-face overrides (ascent-override, descent-override) shrink the layout shift when the swap happens: the difference between a jarring reflow and one nobody notices.

Done well, this is invisible: text appears instantly, the real font slots in, and nothing jumps. Unmanaged fonts are one of the most common, most fixable causes of a sluggish first paint.

Accessibility is built into the type

Readable and accessible typography are mostly the same thing. The system you build for clarity does most of the accessibility work for free, if you make a few non-negotiable choices.

  • Never disable zoom, and never size body text in fixed px that ignores user settings. Use rem so a visitor who sets a larger default font size is respected. Text must reflow and remain usable at 200% zoom.
  • Meet contrast minimums. WCAG AA wants 4.5:1 for normal text and 3:1 for large text. Light-gray-on-white “subtle” copy is the most common contrast failure on the web.
  • Keep body text large enough. A 16px floor for primary content is a floor, not a target. Tiny captions and legal text still need to clear the contrast bar.
  • Don’t carry meaning in weight or color alone. A link distinguished only by hue disappears for some readers. Back it with an underline, a clear state, or actual words.
  • Respect line length and spacing for cognition, too. Generous measure and rhythm aren’t only aesthetic; they reduce reading effort for everyone, including readers with dyslexia and low vision.

None of this is a separate checklist bolted on at the end. It is the same set of decisions, made well: accessibility is a design decision, and type is where that conviction shows up first.

How Strynal builds type systems

Every engagement starts on a blank page. There is no template, no recycled scale carried over from the last client. Typography is one of the first systems we build, because it sets the tone for everything drawn after it. We define the scale, the measure, the rhythm, the font strategy, and the loading plan as one connected system.

Because the team that designs the type is the team that builds it, the scale you approve in design is the scale that ships in CSS: same names, same values, same loading behavior. Strategy, brand, and build sit under one roof, so the type system stays whole instead of fraying across a handoff. If your site’s text feels off and you can’t name why, it’s usually the system underneath. A system is a fixable thing. See how we approach the craft on our UI/UX work.