Typography
WCAG suggests lines no longer than 80 characters and line spacing of at least 1.5 inside paragraphs. Two CSS properties handle both.
Choosing fonts
font-family takes a list of fonts separated by commas. The browser uses the first one that is available on the reader's device and moves down the list if it is missing. Always end the list with a generic family, serif, sans-serif, monospace or system-ui, so that something sensible appears no matter what is installed. Font names that contain spaces go in quotes, as in "Noto Sans KR". system-ui uses the interface font of the operating system, which is well designed, already on the device, and covers many writing systems.
body {
font-family: system-ui, sans-serif;
font-size: 1rem; /* 16px unless the reader changed it */
line-height: 1.6; /* unitless: 1.6 times the font size */
color: #222;
}
h1 { font-size: 2rem; font-weight: 700; line-height: 1.2; }
p { max-width: 65ch; } /* keeps lines a readable length */
.label { text-transform: uppercase; letter-spacing: 0.08em; }You can also load a font file from your own server with an @font-face rule, or from a font service. Web fonts give a page its own character, but each one is a download that delays the text, and Korean, Chinese and Japanese fonts can run to several megabytes because they hold thousands of glyphs. Load as few weights as you need, and keep a good fallback in the list.
Size, weight and line height
font-size sets the size; as the colour and units unit explained, rem keeps text in step with the reader's settings. font-weight goes from 100 (thin) to 900 (black), with 400 as normal and 700 as bold; the keywords normal and bold mean 400 and 700. A font only has the weights its designer made, so asking for 300 in a font that has only 400 and 700 gives you the nearest one.
line-height sets the distance between lines. Give it a plain number with no unit, such as 1.6: it then means 1.6 times the font size of each element, so headings and small print each get spacing that fits them. A value with a unit, such as 24px, is calculated once and inherited as a fixed length, which is too tight for large headings. Body text usually reads well between 1.4 and 1.7; WCAG success criterion 1.4.8 suggests at least 1.5 within paragraphs. Large headings look better tighter, around 1.1 to 1.3.
Line length and alignment
Very long lines are tiring: the eye loses its place when it jumps back to the start of the next line. WCAG 1.4.8 suggests no more than 80 characters per line (40 for Chinese, Japanese and Korean). The easy way to enforce this is max-width in ch units on paragraphs, for example max-width: 65ch. text-align sets alignment: left (or start) is easiest to read for long text in left-to-right languages, center suits short headings, and justify can open up uneven gaps between words.
Small finishing touches
text-transform: uppercase shows text in capitals without changing the HTML, so the source keeps its normal spelling and the style can be changed later in one place. MDN notes that long runs of capitals are harder to read for some people, including people with dyslexia, so keep it for short labels, and add a little letter-spacing, such as 0.08em. text-decoration draws lines: underline, line-through, or none to remove a link's underline (keep some other sign that it is a link). Readers who need more space may override your spacing; WCAG 1.4.12 asks that pages still work when line height is 1.5, letter spacing 0.12em, word spacing 0.16em and paragraph spacing 2em, so avoid boxes with fixed heights that would cut off text.
| font stack | Fonts tried in order; end with a generic family |
| generic family | serif, sans-serif, monospace, system-ui |
| font-weight | 100 to 900; 400 normal, 700 bold |
| unitless line-height | A multiple of each element font size |
| ch | Width of the digit 0; good for line length |
| @font-face | Loads a font file |
| letter-spacing | Space between letters; helps text in capitals |
- Why end a font-family list with a generic family?
- So a suitable font appears even if none of the named ones is installed
- It makes the page load faster
- It is required syntax
- What does font-weight: bold equal?
- font-size is 20px and line-height is 1.5. How tall is each line?
- Why give line-height without a unit?
- Each element multiplies by its own font size
- Units are not allowed
- It makes text bold
- What line length does WCAG 1.4.8 suggest for English text at most?
- Which unit is handy for limiting line length?
- ch
- vh
- deg
- What does text-transform: uppercase change?
- Only how the text is displayed
- The text in the HTML file
- The font family
- font-size is 16px. How much is letter-spacing: 0.1em?
- Which alignment is easiest to read for long paragraphs in English?
- left
- center
- justify
- Why avoid fixed heights on text boxes?
- Text gets cut off when readers increase spacing or size
- Heights are not allowed in CSS
- They slow down scrolling
- font-family is a fallback list ending in a generic family.
- Unitless line-height around 1.5 for body text; tighter for big headings.
- Limit line length with max-width in ch; uppercase needs a little letter-spacing.