Colour, Units and Type
Most of what makes a page feel designed comes down to three things: colour, size and type. CSS gives you several ways to write each one, and they are not interchangeable. A few of the choices on this page decide whether your text is comfortable to read, and whether it stays readable for someone who has told their browser they need it larger.
Units are the heart of it, and a room makes a good picture. You can measure a room in metres, or as "about three of my strides". The metre is the same for everyone. The stride depends on who is walking. CSS has both kinds of unit, and for text, the stride kind is usually the right one, because it grows with the person reading.
Four Ways to Write a Colour
Every colour on a screen is a mix of red, green and blue light, and CSS lets you describe the mix in several notations. Here is one colour, a medium purple, written four ways.
.named {
color: rebeccapurple;
}
.hex {
color: #663399;
}
.rgb {
color: rgb(102 51 153);
}
.hsl {
color: hsl(270 50% 40%);
}
Give four paragraphs these four classes and all four appear in exactly the same purple. The first uses a named colour, one of nearly 150 English names CSS understands, such as navy or darkgreen. The second is a hex code: a hash sign and three pairs of characters, one pair each for red, green and blue, counting in base sixteen from 00, none of that light, to ff, all of it. Hex is what design tools and colour pickers most often hand you.
The third, rgb(), gives the same three amounts as ordinary numbers from 0 to 255. The fourth, hsl(), describes the colour the way people think about it: a hue, as an angle around a colour wheel, then how saturated it is, then how light, both as percentages. HSL is the one to reach for when you want a lighter or darker version of a colour: change only the last number.
A newer notation, oklch(), has been widely available since late 2025. It is built so that equal steps in lightness look equally different to the human eye, which the older notations do not manage. You will see it in newer stylesheets; this book uses hex.
Pixels, and Units That Follow the Reader
The unit you have seen most is px, the pixel. Despite the name, a CSS pixel is not one dot on your screen but a fixed reference size, roughly the size of a dot on an ordinary monitor, and it never changes with the reader's preferences. That makes it right for things like thin borders, and wrong for text.
Every browser has a setting for the default text size, and people with low vision often raise it. The unit rem, short for root em, is measured from that setting: one rem is the root font size, which is 16 pixels unless the reader has changed it. Text sized in rem grows when the reader asks for bigger text. Text sized in pixels ignores them.
.fixed {
font-size: 18px;
}
.flexible {
font-size: 1.125rem;
}
Put these on two paragraphs and, at the browser's normal settings, they look identical: 1.125 times 16 pixels is 18 pixels. Now open Chrome's Settings, choose Appearance, and set the font size to Large, which makes the root size 20 pixels. The paragraph sized in pixels stays at 18. The one sized in rem grows to 22 and a half, as the reader asked. Zooming the page with Ctrl and the plus key, or Cmd and plus on a Mac, is different: zoom enlarges everything, pixels included.
Three more units come up often. An em is measured from the font size of the element itself, or of its parent when you are setting the font size; it suits spacing that should grow with the text around it, but nested ems multiply, so this book keeps text sizes in rem. A percentage, %, is a share of the parent, most often its width. And vw and vh are one percent of the width and height of the viewport, the visible area of the browser window.
Fonts and Font Stacks
The font-family property takes a list of fonts, called a font stack. The browser uses the first one in the list that is available on the visitor's device and skips the rest, so the list always ends with a generic family, such as sans-serif, that every device has.
body {
font-family: system-ui, "Segoe UI", Helvetica, Arial, sans-serif;
}
This is a system font stack. The first entry, system-ui, asks for the font the operating system uses for its own menus and windows, so the page looks at home on Windows, on a Mac and on a phone. The named fonts after it are fallbacks for older devices, and a name with a space in it goes in quotes. The result is clean, familiar text that costs nothing to download.
A site can also bring its own font, called a web font, with an @font-face rule pointing at a font file, or by linking a hosted service such as Google Fonts. Web fonts have two costs. They are extra downloads, and until one arrives the text either waits or shows in a fallback font and then jumps, which Chapter 13 measures. And a font served by another company tells that company about every visit to your page.
Readable Text
How text is laid out matters more for reading than which font it is in. Two properties do most of the work.
main {
max-width: 65ch;
line-height: 1.5;
}
The first stops lines from growing too long. The unit ch is the width of the digit zero in the current font, so 65ch holds roughly 65 characters. Lines of around 60 to 75 characters are the comfortable range; much longer and the eye struggles to find the start of the next line. On a wide window, this rule turns the page's text into a readable column instead of lines that run from edge to edge.
The second sets the height of each line to one and a half times the font size, which opens up the text and makes it more comfortable to read; the browser's default is tighter, around 1.2. Written without a unit, the number scales with whatever font size each element has. A third property, font-weight, sets how heavy the letters are: 400 is normal and 700 is bold.
A First Word on Contrast
Light grey text on a white background looks refined in a design tool and is unreadable for a real share of visitors: people with low vision, older eyes, a cheap screen, or a phone in sunlight. The difference in brightness between text and background is called contrast, and it can be measured. A pale grey of the kind often used for secondary text scores less than 3 to 1 on white, where the usual minimum for body text is 4.5 to 1. Chapter 12 shows how to measure it; until then, when in doubt, make the text darker.
- "Pixels are the precise, professional unit for text." Pixels ignore the reader's chosen text size.
remrespects it, and is equally precise. - "Web fonts are free." Free to use, perhaps, but each one is an extra download that can delay or shift the text, and a hosted one tells its host about your visitors.
- "Grey text looks elegant." Often it is unreadable for part of your audience. Readable contrast is a requirement, not a style.
- Text that respects the reader's own size setting is an accessibility requirement, and using
remmeets it for free. - Line length and line spacing do more for readability than any choice of font.
Knowledge Check
Which unit makes text grow when a reader raises their browser's default font size?
- The pixel,
px, since it is exact - The viewport unit,
vw, since it scales - The root em,
rem, based on the root size - The percentage,
%, of the parent width
What is a font stack for?
- Offering fallbacks in case a font is not available
- Mixing several fonts together in the same text
- Loading every listed font so the page is faster
- Choosing a different font for each font weight
Which rule gives body text a comfortable line length?
- A
widthof 100vw, so text fills the window - A
line-heightof 3, so lines stand apart - A
font-sizeof 10px, so more words fit - A
max-widthof 65ch, about 65 characters
Why is HSL handy when you need a darker shade of a colour?
- It turns every colour into a named colour
- Lightness is its own number you can lower
- It can show colours that hex cannot show
- Browsers display HSL faster than hex codes
You got correct