Skip to content

Colour Contrast and WCAG in Practice

Sep 2, 2026 · Tooling

Colour contrast under WCAG is a single number between 1:1 and 21:1 computed from the relative luminance of two colours, and the accessibility thresholds are fixed: 4.5:1 for normal text and 3:1 for large text at Level AA, rising to 7:1 and 4.5:1 at Level AAA. Those numbers are not stylistic preferences; they come from a defined formula, and understanding how the ratio is calculated tells you why some colour pairs that look fine to you still fail. This article explains the ratio, the exact thresholds, how relative luminance is derived from an RGB colour, and how to hit the targets in real designs.

What does the contrast ratio actually measure?

The contrast ratio measures the difference in luminance — perceived brightness — between two colours, not the difference in hue. It is defined as:

ratio = (L1 + 0.05) / (L2 + 0.05)

where L1 is the relative luminance of the lighter colour and L2 that of the darker. Because relative luminance ranges from 0 (black) to 1 (white), the ratio spans from 1:1 when the two colours are identical to 21:1 for pure black on pure white. You can check the endpoints by hand: white has luminance 1 and black has 0, so (1 + 0.05) / (0 + 0.05) = 1.05 / 0.05 = 21. The + 0.05 term represents ambient light reflecting off a screen; it keeps the ratio finite and prevents division by zero when one colour is pure black.

The key consequence is that hue barely matters on its own. A saturated red and a saturated green can look wildly different and still sit close in luminance, which is exactly why red text on a green background can be both garish and non-compliant. Contrast is about light and dark, so two colours must differ enough in luminance, regardless of how different they are in colour.

What are the real WCAG thresholds?

WCAG defines separate minimums for normal and large text at each conformance level, and it is worth stating them precisely because they are widely misquoted.

Content Level AA Level AAA
Normal text 4.5:1 7:1
Large text 3:1 4.5:1
UI components & graphics (non-text) 3:1 3:1

Two definitions make these usable. Large text means at least 18pt (roughly 24px) at a regular weight, or at least 14pt (roughly 18.66px) when bold — bold lowers the size threshold because thicker strokes are easier to read at a given contrast. Non-text contrast, from success criterion 1.4.11, applies to things that are not letters but still carry meaning: the border of a text input, a toggle in its “on” state, an icon that communicates status. Those need 3:1 against their neighbours. Note that the non-text minimum does not rise at AAA; 1.4.11 is a AA criterion, and there is no stricter AAA version of it.

A few things explicitly get a pass: purely decorative graphics, logos, and disabled controls are exempt from the text and non-text contrast requirements. That is a genuine part of the standard, not a loophole — but treat it narrowly, because “decorative” means the element conveys no information a user needs.

How is relative luminance calculated?

Relative luminance is computed by linearising each RGB channel and then combining them with weights that reflect human vision. The process has two steps. First, take each 8-bit channel and normalise it to the range 0 to 1 by dividing by 255. Then apply the sRGB gamma correction to each channel to recover its linear-light value:

for each channel c in {R, G, B}, with c in [0, 1]:
    if c <= 0.03928:
        c_lin = c / 12.92
    else:
        c_lin = ((c + 0.055) / 1.055) ^ 2.4

Screens encode colour with a non-linear curve so that more of the available values land where the eye is sensitive; this step undoes that curve so the numbers represent actual light intensity. Second, combine the three linear channels:

L = 0.2126 * R_lin + 0.7152 * G_lin + 0.0722 * B_lin

The weights are the revealing part. Green contributes about 72% of perceived luminance, red about 21%, and blue only about 7%, because the human eye is far more sensitive to green light than to blue. This is why changing the blue channel of a colour barely moves its contrast ratio, while nudging the green channel moves it a lot. It also explains a common surprise: a bright, cheerful yellow (high red and green) has very high luminance and therefore poor contrast against white, whereas a deep blue (low luminance) contrasts strongly against white even though blue “feels” like a light, cool colour.

You rarely compute this by hand, but knowing the mechanism lets you predict the outcome. If you want more contrast, change the luminance — move one colour toward black or white, or adjust the green and red channels — rather than merely shifting the hue.

Why do colours that look fine still fail?

They fail because your eye adapts and the formula does not. When you have been looking at a design for an hour, mid-grey text on a white card can feel perfectly readable, yet #999999 on #ffffff computes to roughly 2.85:1 — below the 3:1 large-text floor and well under the 4.5:1 needed for body copy. A slightly darker grey such as #767676 on white clears 4.5:1. The gap between “looks okay to me” and “meets the threshold” is exactly the gap the standard exists to close, because many users — with low vision, in bright sunlight, on a cheap panel — do not have your viewing conditions.

Placeholder text is a repeat offender: the light grey that signals “this is a hint, not real input” is often the least readable text on the page, and it frequently fails. Coloured links inside body text are another: a link colour chosen to look pleasant against white can drop below 4.5:1, and if you rely on colour alone to mark links you also fail a separate criterion about not using colour as the only cue. When contrast is borderline, the fix is almost always to change luminance, and a converter makes that quick — you can move a colour between hex, RGB, and HSL, then lower the lightness a few steps and recheck. Our client-side colour converter does this in the browser, so you can iterate on values locally without sending your palette anywhere.

What are practical tips for meeting the thresholds?

Design for the ratio from the start rather than auditing at the end. A handful of habits cover most cases:

  • Aim past the minimum. Targeting 4.5:1 exactly leaves no margin for a stakeholder who wants the grey “a touch lighter.” Aiming for 7:1 on body text buys you room and happens to meet AAA.
  • Use luminance, not hue, as your lever. If a brand colour fails against white, darken it for text use and keep the original for large decorative fills where the 3:1 non-text rule applies.
  • Do not signal with colour alone. Underline links, add an icon to an error, or label a status — so that users who cannot distinguish the hues still get the message. This is a distinct requirement from contrast, and passing one does not satisfy the other.
  • Check both themes. A pair that passes in light mode can fail when you invert to dark mode, because luminance relationships change. Verify each theme independently.
  • Remember state colours. Hover, focus, and disabled variants each need to hold up; focus indicators in particular fall under the 3:1 non-text rule.

The reassuring part of contrast accessibility is that, unlike much of design, it is objective. The ratio is a formula, the thresholds are fixed numbers, and a colour pair either clears them or it does not. That means you can settle the question with arithmetic instead of opinion: compute the two luminances, take (L1 + 0.05) / (L2 + 0.05), and compare against 4.5, 3, 7, or 4.5 depending on the text size and the level you are targeting. Build that check into your workflow and accessible contrast stops being a last-minute scramble and becomes a property your palette simply has.

Frequently asked questions

What is the minimum contrast ratio for normal text?

WCAG 2 Level AA requires a contrast ratio of at least 4.5:1 for normal body text against its background. Level AAA raises that to 7:1.

What counts as large text?

Large text is at least 18pt (about 24px) for regular weight, or at least 14pt (about 18.66px) when bold. Large text needs only 3:1 for AA and 4.5:1 for AAA.

What is the highest possible contrast ratio?

21:1, produced by pure black on pure white. The scale runs from 1:1 (identical colours) up to 21:1.

Does contrast depend only on hue?

No. The ratio is computed from relative luminance, which weights green most and blue least. Two colours can look different in hue yet fail contrast because their luminance is close.

Do icons and buttons need to meet a contrast ratio too?

Yes. WCAG 1.4.11 (non-text contrast) requires at least 3:1 for meaningful UI components and graphical objects, such as an input border or an icon that conveys state.

Contact: contact@quikconsolecom.net