Fonts and Text: Family, Size, Weight and Spacing
A handful of text properties (font-family with fallbacks, font-size, font-weight, font-style, line-height, text-align, text-transform, letter-spacing and text-decoration) turn plain words into text people can read at a glance.
Novice · CSS · Updated
After this lesson you can
- Choose a font with font-family and a list of fallbacks that ends in a generic family
- Set text size, weight, style and line spacing with font-size, font-weight, font-style and a unitless line-height
- Align and decorate text with text-align, text-transform, letter-spacing and text-decoration
Key takeaways
- font-family takes a list of fonts. The browser uses the first one it has, so end the list with a generic family such as
sans-serif. - Size text in rem.
1remis the reader's normal text size, so your page follows their own browser setting. - font-weight sets how bold text is (400 is normal, 700 is bold), and
font-style: italicslants it. - A line-height with no unit, such as
1.5, sets the space between lines as a multiple of the text's own size. - text-align, text-transform, letter-spacing and text-decoration line text up, change its capitals, space it out, and underline or cross it out.
A good menu board can be read from the sidewalk: big, bold names, prices that stand out, and enough room between the lines that your eye doesn't slip. A bad one is a wall of tiny, cramped letters, and people walk on by. Web pages work the same way. Most of what's on any page is text, so you'll use the properties in this lesson on everything you build: a résumé page, a class report, a blog, the Sol Taco Truck menu.
font-family: a list, best choice first
Ordering at the truck window, you might say: "a horchata, please; if you're out, an agua fresca; if not, any cold drink." You get your first choice if they have it, and something close if they don't.
font-family works the same way. A browser can only use a font that's on the reader's device (or one the page sends along, which is the next lesson), so you give it a list, best choice first. That list is called a font stack, and the fonts after the first are its fallbacks:
body {
font-family: "Trebuchet MS", Verdana, sans-serif;
}
h1 {
font-family: Georgia, "Times New Roman", serif;
}
Put quotes around a font name that has spaces in it, such as "Trebuchet MS". The last item in each list is a generic family, a kind of font that every browser has some version of, so the list always ends with a match:
| Generic family | What it looks like | Good for |
|---|---|---|
serif |
small strokes ("feet") at the ends of letters | a classic, bookish look |
sans-serif |
no feet: clean, plain letters | most body text on screens |
monospace |
every letter the same width | code, receipts, prices in columns |
system-ui |
the device's own interface font | pages that feel like an app |
cursive |
handwriting-like letters | a short, playful touch |
Generic family names never take quotes: sans-serif, not "sans-serif". In quotes, the browser looks for a font actually named sans-serif.
Try it. In your sol-taco-truck page (or any page), give the body the first stack above. Then misspell the first font, as "Trebuchet": nothing breaks, and the browser moves on to Verdana. To see which font it really used, select some text in the developer tools' Elements panel and scroll to the bottom of the Computed pane: Rendered Fonts names it. (In Firefox, it's the Fonts pane.)
font-size, and the rem unit
font-size sets how big the letters are. The unit that suits text best is rem, read "rem". 1rem is the reader's normal text size, which is 16 pixels in most browsers unless the reader has changed it:
body {
font-size: 1.125rem;
}
h1 {
font-size: 2.5rem;
}
The body text is 1.125 times the normal size, which is 18 pixels for most readers, and the heading 2.5 times, 40 pixels. Here's why rem beats pixels for text: someone who has set their browser to bigger text gets bigger text on your page too, because everything is measured from their normal size. With font-size: 16px, the size is fixed, whatever the reader asked for. (Units: px, rem, em, % and Viewport Units, in the next chapter, covers every unit.)
font-weight and font-style
font-weight sets how bold text is, with a number: 100 is thin, 900 is very heavy, and most fonts come in steps of 100 between them. Two have names: 400 is normal, and 700 is bold. font-style: italic slants the letters, and font-style: normal straightens them again.
.price {
font-weight: 700;
}
.tagline {
font-style: italic;
}
Every price turns bold, and the tagline under the truck's name leans to the right. A font comes with only some weights. Ask for one it doesn't have, and the browser uses the nearest one it has, or draws a fake bold or italic, which never looks quite as good as the real thing. The next lesson shows how to load the weights you need.
line-height: room between the lines
Notebook paper comes wide-ruled and college-ruled: the same words, but on wide-ruled paper the lines sit farther apart. line-height is how far apart your lines of text sit. Give it a number with no unit, and it's a multiple of the text's own size:
body {
font-size: 1.125rem;
line-height: 1.5;
}
h1 {
line-height: 1.1;
}
For 18-pixel body text, 1.5 gives lines 27 pixels apart, a comfortable rhythm: body text reads well at about 1.4 to 1.6. Big headings look better tighter, around 1.1 to 1.2.
Why no unit? A number scales with each element's own size. Write line-height: 24px on the body instead, and every element inside it gets 24-pixel lines, including a 40-pixel heading, whose lines would then crash into each other if it wrapped onto two. With 1.5, the heading gets lines 1.5 times its size.
Try it. Paste a long paragraph into your page (two or three menu descriptions in a row will do). Set its line-height to 1, then 1.5, then 2.5, saving after each. Which reads best, and which makes the lines feel like they're floating apart?
text-align, text-transform and letter-spacing
The truck's section headings are painted in capital letters, spaced out a little and centered. Three properties do that:
h2 {
text-align: center;
text-transform: uppercase;
letter-spacing: 0.1em;
}
text-alignlines text up:left(the usual for English),right,center, orjustify, which stretches each line to both edges.text-transform: uppercaseshows text in capitals. The HTML still says Tacos: only the look changes, so if the design changes later, you change one line of CSS instead of retyping every heading. There's alsolowercase,capitalize(a capital at the start of each word) andnone.letter-spacingadds room between letters.0.1emis a tenth of the text's own size (an em is the size of the element's own font), so the spacing grows with the text. Capitals look better with a little extra room; lowercase body text is best left alone.
text-decoration: underlines and cross-outs
text-decoration draws a line under, over or through text. The value you'll use most is line-through, for a price that has dropped:
.old-price {
text-decoration: line-through;
}
.menu-link {
text-decoration: none;
}
<p>Chicken tinga burrito <span class="old-price">$10.00</span> <span class="price">$8.50</span></p>
The old price is crossed out beside the new one, the way a sale sign shows it. underline adds an underline, and none takes one away, which is how sites remove the underline from links in a menu bar.
Take care with that last one. In a paragraph of text, the underline is how readers spot a link, and some people can't tell the link's color from the text around it. Keep links in your paragraphs underlined, and remove the underline only where it's clear from the design that something is a link, such as a menu bar of buttons.
Check yourself
2 questions to try on the lesson page.
So what
Text is most of every page you'll build. A font stack with a fallback, sizes in rem, a unitless line-height and a few finishing properties make the difference between a page people read and a page they leave.