Colour Contrast Pair Generator
Two tools in one: draw a text-and-background pair that reaches a contrast target you choose, or paste two colours you already have and see their real ratio against the WCAG thresholds.
What this generator does
Answers the perceptual question the harmony generators cannot. Those tools arrange hues geometrically, and hue relationships say nothing about readability — two colours can be perfect complements and completely illegible together. This measures actual luminance contrast, which is what determines whether text can be read.
How to use this tool
- Pick the ratio you need — 4.5:1 for body text, 3:1 for large text, 7:1 for AAA.
- Press Generate a pair to draw colours that reach it.
- Or scroll to the checker and paste two hex values.
- Read the ratio and which thresholds it passes.
Understanding the controls
- Target ratio
- 4.5:1 is the WCAG AA threshold for body text, 3:1 for large text (24px, or 18.66px bold), and 7:1 is AAA. The generator keeps drawing until it reaches the one you pick.
- The checker's two colours
- Hex values, with or without the hash; the three-digit short form works too. The ratio and the thresholds it passes update as you type.
- Seed
- Brings the same generated pair back, so a colour chosen for a project can be recovered.
Worked examples
- Black on white
- 21:1 — the maximum possible, and the only pair that reaches it.
- #767676 on white
- 4.54:1 — the canonical grey that just passes AA for body text.
- #949494 on white
- About 3:1 — passes for large text only, and fails for body text.
Common use cases
- Checking a brand colour is usable for body text before committing to it
- Finding a readable accent colour for links or buttons
- Auditing an existing palette against WCAG thresholds
- Teaching why some colour pairs are unreadable despite looking fine
- Choosing chart or label colours that stay legible
How this generator works
The ratio follows the WCAG 2.x definition exactly. Each colour channel is normalised to 0–1 and linearised through the sRGB transfer function — dividing by 12.92 below the 0.04045 threshold, and raising ((c + 0.055) / 1.055) to the power 2.4 above it. Those linear values are weighted 0.2126 red, 0.7152 green and 0.0722 blue into a relative luminance, and the two luminances combine as (lighter + 0.05) / (darker + 0.05). The linearisation step is the one a naive implementation skips, and skipping it produces confidently wrong answers; black on white here comes to exactly 21:1, as it must.
Randomness and fairness
The generator draws hue, saturation and lightness at random and widens the lightness gap between the two colours as attempts go on, so a high target is reached by genuinely separating lightness rather than by luck. Every pair's ratio is computed from the two swatches actually produced, so the number shown is measured rather than assumed.
For how randomness is produced across the whole site, see how Generate Random works.
Limitations and good to know
- A contrast ratio is a necessary condition for readable text, not a sufficient one. It says nothing about font weight, size beyond the large-text threshold, letter spacing, or the rest of a page — so a passing ratio is one criterion rather than a verdict on accessibility.
- The calculation is for text on a solid background. Text over a gradient, an image or a translucent layer has a varying ratio, and you should check the worst point rather than an average.
- WCAG 2.x contrast is itself a simplification of how vision works and is known to treat some colour pairs — dark backgrounds especially — more generously than they deserve. Newer approaches exist but are not what WCAG 2.2 requires.
- Targets above about 12:1 exist only very near black and white, so the generator reports honestly when it cannot reach one rather than presenting a near-miss as a pass.
- Nothing here checks non-text contrast requirements, which have their own separate WCAG criterion.
Common mistakes
- Treating a passing ratio as making a design accessible
- It is one criterion. Font size, weight, spacing, focus states and much else all matter, and none of them is measured here.
- Checking text against the average colour of a gradient or image
- Check the worst point instead — that is where the text will fail. Better still, put a solid layer behind the text.
- Using the 3:1 large-text threshold for ordinary body copy
- Large means 24px, or 18.66px bold, and above. Anything smaller needs 4.5:1.
Practical tips
- Check your brand colour against both white and black early — knowing which way round it works saves a great deal of rework.
- Aim above the threshold rather than at it; a ratio of 4.51:1 leaves no margin for a rendering difference or a future tweak.
Privacy and your data
Both the generator and the checker run entirely in your browser. No colour values are uploaded, stored or written into the page address. Analytics records only that a pair was produced.
Frequently asked questions
- What contrast ratio do I need?
- 4.5:1 for body text under WCAG AA, 3:1 for large text (24px, or 18.66px bold), and 7:1 for AAA.
- How is the ratio calculated?
- Each channel is linearised through the sRGB curve, weighted into relative luminance, and the two combined as (lighter + 0.05) / (darker + 0.05).
- Does passing mean my design is accessible?
- No. It means one criterion is met. Size, weight, spacing, focus indication and much else are not measured by a contrast ratio.
- Why is the maximum 21:1?
- That is black against white — luminance 0 against luminance 1, so (1 + 0.05) / (0 + 0.05) = 21.
Related generators
- Colour Palette GeneratorGenerate a real colour palette — six harmony types, with hex, RGB and HSL values and the contrast each colour gives with text.
- Complementary Colour GeneratorFind the colour directly opposite any hue on the wheel, with hex, RGB and HSL values and the contrast each gives with text.
- Random Gradient GeneratorGenerate a CSS gradient that moves through hue rather than through grey, with every stop's colour and position shown.