Lesson 06 · Part 2 · CSS

Styling content

CSS decides how your page looks, and good looks can still lock people out. Colour, size, and motion must hold up when someone zooms in, has weak vision, sees colours differently, or asks their device to calm down.

In one minute

In plain words

Imagine a road sign. If the letters are pale grey on a white sign, only people with perfect eyesight in perfect light can read it. If the sign says "turn" only by being red, drivers who cannot tell red from green miss it. If the sign is tiny, or spins, many people give up. CSS is the paint on your road signs. This lesson is about painting them so everyone can read them.

1. Contrast: how different are text and background?

Contrast ratio is a number from 1 (identical colours) to 21 (black on white). It compares how light the text is with how light the background is. WCAG 2.2 criterion 1.4.3 asks for 4.5 : 1 for normal text and 3 : 1 for large text (about 24 px, or about 19 px bold). Criterion 1.4.11 asks for 3 : 1 for icons, input borders, and focus rings. Weak contrast hurts people with low vision, but also anyone reading in sunlight or on a dim screen.

Lab: fade the text and watch the number

Step 1. Drag the slider. The text colour is a mix of the theme text colour and the background. The ratio is calculated live.

Orders placed before 14:00 leave the same day.

Contrast ratio: 21.0 : 1

Passes.

A screen reader reads the words the same at any contrast. That is why contrast problems are easy to miss if you only test with your ears. Test with a checker (browser devtools show the ratio when you inspect a colour), and re-test in dark mode, which has its own colours. Gradients and background images need a check at the worst spot behind the text.

2. Colour is not the only channel

About 1 in 12 men and 1 in 200 women have some colour-vision difference. Others use a black-and-white display or a bright-sun screen. WCAG 1.4.1 says: do not use colour alone to show an error, a required field, a link, or a chart series. A screen reader user gets nothing from a colour either, so a text clue helps them too.

Lab: required field, with and without a text clue

Step 2. Pick the markup, then switch the view to grayscale to see what colour-blind or monochrome users see.


          
Fails.

Links follow the same rule. Links inside a paragraph should keep their underline (or another non-colour cue with 3 : 1 contrast). The lab toggles the underline too: the "text" version underlines the link.

3. Units: let the text grow

Many people raise their browser's default text size instead of zooming. A font size written in px ignores that setting. A size in rem (a multiple of the root font size) respects it. WCAG 1.4.4 requires text to scale to 200% without losing content, 1.4.10 (Reflow) requires no sideways scrolling at 320 CSS pixels wide (that is 400% zoom on a desktop), and 1.4.12 requires that your layout survives wider line, letter, and word spacing.

Lab: change the "browser default" and compare

Step 3. Pick a default text size, as if the user had set it in browser settings.

font-size: 16px ✕ ignores the setting

Delivery is free over 50 euros.

font-size: 1rem ✓ follows the setting

Delivery is free over 50 euros.

4. Target size: can a thumb or a tremor hit it?

WCAG 2.2 criterion 2.5.8 (AA) asks for targets of at least 24 by 24 CSS pixels, or enough spacing around smaller ones. Criterion 2.5.5 (AAA) suggests 44 by 44. Small targets hurt people with hand tremors, people using a switch or head pointer, and anyone on a bumpy bus.

Lab: try to hit the small buttons

Step 4. Choose a size. Then click or tap the row of buttons, or Tab through them.

No rating chosen yet.

Fails.

Make a small icon bigger without changing how it looks by adding padding to the button, not by growing the icon.

5. Motion: stop when asked

Spinning, sliding, and parallax effects can cause dizziness, nausea, or migraines for people with vestibular disorders. They also distract people with attention difficulties. Operating systems have a "reduce motion" setting. CSS can read it with @media (prefers-reduced-motion: reduce). Stop decorative motion. If motion carries meaning (a progress bar), keep the meaning and add text. Anything that moves for more than 5 seconds needs a pause control (WCAG 2.2.2), and nothing should flash more than three times a second (2.3.1).

Lab: the spinner

Step 5. Flip the switch to pretend your device has reduce motion turned on.

Saving your draft (in progress)

@media (prefers-reduced-motion: reduce) {
  .spin { animation: none; }
}
Spinner is moving.

In devtools, open the Rendering panel and emulate prefers-reduced-motion: reduce to test the real thing. Also check forced colours (Windows high-contrast mode): backgrounds and shadows are removed, so borders and text must still carry the design.

Common mistakes

You seeWhy it is a problemFix
Light grey placeholder or helper textBelow 4.5 : 1, unreadable for many.Darken until the checker passes.
Red border as the only error cueInvisible in grayscale and to screen readers.Add text and an icon.
font-size: 14px everywhereIgnores the user's default size.Use rem.
Links without underline in body textColour alone marks them.Keep underline.
16 px icon buttons side by sideHard to hit, easy to mis-tap.Pad to 24 px or more.
Infinite spinning decorationMakes some people ill.Honour prefers-reduced-motion.
Try it yourself
  1. Zoom this page to 400%. Does any text get cut off or force sideways scrolling?
  2. In devtools, emulate prefers-reduced-motion: reduce and reload. The spinner in lab 5 should sit still.
  3. Inspect a grey text colour and read the contrast ratio the devtools show.

Remember

Edit this example in the playground