Lesson 1 · CSS Fundamentals

Colour and Contrast: Making Text Readable

Learn how contrast ratios work, what WCAG 2.2 asks for normal and large text, and how to fix a grey or brand colour that fails, with checked examples.

  • Beginner
  • 10 min
  • ✓ Completed

What you’ll learn

  • Explain what a contrast ratio measures
  • Apply the WCAG 2.2 thresholds for normal text, large text and UI parts
  • Fix a failing colour without changing the design's character

The idea in plain language

A Contrast ratio A measure from 1:1 to 21:1 of how different two colours are in brightness, calculated from their relative luminance. WCAG 2.2 asks for at least 4.5:1 for normal text and 3:1 for large text so that people with low vision can read it. See the glossary compares how light two colours are. It runs from 1:1 (the same colour twice, unreadable) to 21:1 (black on white). The ratio is calculated from each colour’s relative luminance – how bright it looks to the eye, with green counting most and blue least – using the formula (lighter + 0.05) ÷ (darker + 0.05). Hue does not matter: a red and a green of the same lightness can be nearly impossible to tell apart.

What WCAG 2.2 asks for

The Web Content Accessibility Guidelines set minimum ratios so that people with low vision or a poor screen can still read the page:

What AA (the usual target) AAA (enhanced)
Normal text 4.5:1 7:1
Large text (24px, or about 18.7px bold) 3:1 4.5:1
Icons, input borders, focus rings (non-text) 3:1 –

Large text gets a lower threshold because bigger letters stay legible at lower contrast. Note the trap: bold alone does not make text large. A 16px bold button label still needs 4.5:1.

Worked example: four real colour pairs

We ran these pairs through our Color Contrast Checker, which uses the WCAG formula:

Text Background Size Ratio AA result
#767676 grey #FFFFFF white 16px 4.54:1 Pass (just)
#9CA3AF light grey #FFFFFF white 16px 2.54:1 Fail
#9CA3AF light grey #FFFFFF white 24px 2.54:1 Fail (below 3:1)
#FFFFFF white, bold #C4623A terracotta 16px 4.07:1 Fail
#FFFFFF white, bold #A34A28 dark terracotta 16px 5.89:1 Pass

Two lessons hide in this table. First, the popular “placeholder grey” #9CA3AF fails even at large sizes. Second, a brand colour can be one shade away from passing: this site uses the darker #A34A28 for buttons and the lighter #C4623A only for large decorative areas.

Fixing a colour that fails

Because contrast depends on lightness, the cleanest fix is to keep the hue and change only how light the colour is. The checker’s suggestion feature does exactly that: for #9CA3AF on white with a 4.5:1 target it proposes #6F7681, which measures 4.58:1 – still a cool grey, now readable. Working in a perceptual colour space such as OKLCH A CSS colour space that describes a colour by perceptual lightness (L), chroma (C, colourfulness) and hue (H). Because equal steps look roughly equal to the eye, it is useful for building colour palettes and smooth gradients, written as oklch(70% 0.15 250). See the glossary makes this easy by hand, because you can lower the L value and leave chroma and hue alone.

Common mistakes

  • Checking only the brand colour, not every state. Hover, disabled and placeholder colours need checking too (disabled controls are exempt, placeholders are not).
  • Forgetting borders and icons. An input whose border is 1.5:1 against the page is hard to find; WCAG 1.4.11 asks for 3:1.
  • Text on images or gradients. Measure against the lightest part behind the text, as the next lesson shows.

Try it

Open the Color Contrast Checker, paste your text and background colours, set the font size, and use the suggestion to get the nearest passing colour. Then check your palette’s lighter and darker shades with the Color Converter.

Check your understanding

Five questions. Choose an answer for each, then check. You can try again as often as you like.

Question 1 What is the minimum WCAG 2.2 AA contrast ratio for normal-size body text?
Question 2 Which text counts as large under WCAG?
Question 3 Grey #9CA3AF on white measures 2.54:1. For normal body text it…
Question 4 White bold 16px text on #C4623A measures 4.07:1. What is the result?
Question 5 What is the safest way to fix a colour that fails?

Quiz progress is saved in this browser only. Nothing is sent to us.

Sources

  1. Understanding Success Criterion 1.4.3: Contrast (Minimum) – W3C Web Accessibility Initiative
  2. Understanding Success Criterion 1.4.11: Non-text Contrast – W3C Web Accessibility Initiative
  3. CSS Color Module Level 4 – W3C

Educational content only. It explains how things work in general and is not financial, tax or legal advice for your situation. The lessons are free and educational. We don't issue certificates or credentials, and nothing here is personal financial advice.