Typography: Fonts, Line Height, and Readability
· 5 min read
You now know how to size things with rem and color things with hex and hsl.
You now know how to size things with rem and color things with hex and hsl. This lesson focuses specifically on typography: the craft of making text pleasant and easy to read, which is honestly one of the highest-impact things you can learn in CSS, because almost every website is, at its core, mostly text.
Choosing Font Families
Let's start with font-family. Browsers come with a small set of safe default fonts, but the real way text looks modern is by specifying a stack of fonts, with fallbacks in case the first choice isn't available on a user's device.
body {
font-family: "Helvetica Neue", Arial, sans-serif;
}
The browser tries each font in order, left to right, and uses the first one it can find installed, falling back to the next. The last item should always be a generic family like sans-serif, serif, or monospace, so that even on a system missing every named font, the text still renders in a reasonable style rather than some completely unexpected default.
A very common beginner mistake is picking a fancy font for body text that is hard to read at small sizes, or forgetting fallbacks entirely and ending up with inconsistent fonts across different computers. For body paragraphs, simple and highly legible fonts almost always beat decorative ones; save decorative fonts for large headings only, if at all.
Font-weight controls boldness, and modern CSS lets you use numeric values from 100 (thinnest) to 900 (boldest), though many fonts only actually support a handful of these.
h1 {
font-weight: 700;
}
p {
font-weight: 400;
}
Line Height And Readability
Now, line-height, which might be the single most underused property by beginners, and the one with the biggest visible impact on readability. Line-height controls the vertical space between lines of text within the same paragraph. The default browser value is quite tight, and long paragraphs with tight line-height feel cramped and tiring to read.
p {
font-size: 1rem;
line-height: 1.6;
}
Notice that 1.6 has no unit. That is intentional and recommended: a unitless line-height is a multiplier of the element's own font size, so it stays proportional even if the font size changes later (through responsive design, for example). A common beginner mistake is setting line-height in px, which then breaks or looks wrong the moment the font size is adjusted elsewhere. For general body text, something between 1.4 and 1.7 is a comfortable range; headings usually look better tighter, often close to 1.1 to 1.3, since large bold text doesn't need as much breathing room.
Letter Spacing And Line Length
Letter-spacing (tracking) can help or hurt readability depending on how it's used. A small amount of positive letter-spacing on uppercase headings often improves readability, because capital letters packed tightly can feel cramped.
.section-label {
text-transform: uppercase;
letter-spacing: 0.08em;
font-size: 0.875rem;
font-weight: 600;
}
Notice letter-spacing is written in em here rather than px, which keeps the spacing proportional to the font size, the same reasoning as unitless line-height.
Text alignment and line length also matter more than beginners expect. Fully justified text (text-align: justify) can create ugly uneven gaps between words, especially in narrow columns, so it's used far less on the web than in print. More importantly, very long line lengths are tiring to read. A common best practice is limiting a text block's width using max-width, often expressed in ch units (roughly the width of one character), to keep comfortable line lengths.
article p {
max-width: 65ch;
line-height: 1.6;
}
This keeps each line of text at a readable length no matter how wide the user's browser window is, which is a small detail that makes long articles dramatically easier to read.
Font Loading And Headings
Font loading is another practical detail worth a mention, even briefly. If you use a custom web font (loaded through something like Google Fonts) instead of a system font, there's a short window where the browser hasn't finished downloading it yet. By default, some browsers hide text entirely until the custom font arrives, which can cause an annoying flash of invisible text on a slow connection. The font-display: swap setting, usually added where the font is declared, tells the browser to show a fallback font immediately and swap to the custom one once it loads, so readers always see something right away rather than staring at a blank page.
Headings deserve a slightly different typographic treatment than body text, beyond just being bigger and bolder. A common, polished pattern is giving headings a tighter line-height, a slightly tighter letter-spacing for very large sizes, and sometimes a different, more distinctive font-family than the body text, while keeping that distinct font limited to headings only, so the page still feels cohesive rather than cluttered with too many competing typefaces. A good rule of thumb for beginners is to use no more than two font families on a single page: one for body text, optionally a second for headings.
Practical Tips And Exercise
Practical tip: when building any text-heavy page, set three things deliberately rather than leaving them at browser defaults: font-family with proper fallbacks, line-height around 1.5 to 1.6 for paragraphs, and a max-width on your text container. These three alone fix most of the "this page feels uncomfortable to read" problem beginners run into without knowing why.
Before you move on, try this: take a few paragraphs of placeholder text describing Tony Stark's background, style it with a sans-serif font stack, a comfortable line-height, and a max-width around 65ch, then compare it side by side with the browser's default styling. The difference in comfort should be obvious immediately.
KEEP READING