OKLCH Studio · Guides

How to fix colour contrast without changing your brand colours

Updated 2026-10-17

A failing contrast check usually triggers one of two bad reactions: pick a different colour entirely, or darken everything until it is black. Neither is necessary. Most failures are small, a few percentage points short of the line, and a small, targeted change in one property is enough. That property is lightness.

This guide shows the method, explains why working in OKLCH keeps the brand look, and walks through six real examples produced by the same Fix logic that runs in this site's contrast checker. Out of the six, 5 needed a darker text colour and 1 needed a lighter one.

Why contrast checks fail

Contrast failures cluster in a few places. Brand colours are often chosen as mid-tones, because they look good as accents and logos, and mid-tones are the worst performers as text: not dark enough for white backgrounds, not light enough for dark ones. Greys used for secondary text and placeholders drift too light. Coloured text on a tinted surface loses contrast from both directions. And buttons with white labels on bright fills, such as amber, green or sky blue, often miss the mark.

The WCAG 2.x thresholds are 4.5:1 for normal text and 3:1 for large text and UI components, as explained in the guide to WCAG and APCA. The distance between your current ratio and the threshold is what you need to close. Often it is less than you expect.

Why change lightness and nothing else

Contrast between two colours is mostly a difference in luminance, and OKLCH has a lightness channel that tracks perceived brightness. That means you can raise or lower contrast by moving L, and leave chroma and hue where they are. The result still looks like the same colour family: a blue stays the same blue, only deeper or paler. Changing hue to fix contrast, by contrast, produces a visibly different colour, and changing chroma usually does little for contrast while making the colour duller.

Doing the same thing in HSL is possible, but HSL lightness moves luminance unevenly from hue to hue, so the same step can overshoot in one colour and undershoot in another. In OKLCH the relationship is steadier, which makes an automatic search practical. See OKLCH vs HSL for measurements.

The method, step by step

  • Measure. Compute the WCAG ratio for the text and its background. Note the target: 4.5:1 for normal text, 3:1 for large text or UI parts.
  • Choose what to change. Usually the text colour. If the background is the problem, for example a tinted card, change the background instead. Never change both unless you must.
  • Convert to OKLCH and keep the chroma and hue values fixed.
  • Move lightness toward more contrast (darker text on a light background, lighter text on a dark one) in small steps, re-measuring each time, and stop at the first value that clears the threshold. The nearest passing lightness is the one that disturbs the design least.
  • Convert back to the format you ship, and check that the colour still fits the gamut. If it does not, chroma is reduced slightly to fit.
  • Re-check in context: hover and focus states, disabled states, text over images, and dark mode.
  • Save the result as a token so the fix is applied everywhere, not just on one component.

A small detail: a result that is 0.01 short of the target is still a fail. Accessibility tools should never round 4.49 up to 4.5, so the fixed ratios in this guide are floored to two decimals.

A worked example

Take Tailwind's blue-400, #51a2ff, as text on white. In OKLCH it is oklch(0.704 0.158 253.6), and its contrast ratio on white is 2.63:1, well short of 4.5:1. The Fix search keeps chroma and hue and moves lightness until the ratio passes. It lands on oklch(0.544 0.158 253.6), which is #1870c8 in hex, with a ratio of 5.01:1.

Before and after in CSS

/* before: fails AA on white */
color: oklch(0.704 0.158 253.6);

/* after: same hue and chroma, lower lightness */
color: oklch(0.544 0.158 253.6);

Only the first number changed. The colour is still recognisably the same blue, but deep enough to read on a white page.

Six computed examples

The table lists six failing pairs, each repaired with the site's Fix logic: lightness is searched in both directions in steps of 0.02, the nearest value that reaches AA 4.5:1 is chosen, and chroma and hue stay fixed. Each row links to its pair page when that pair is in the indexed set, and otherwise to the contrast checker where you can try the same colours.

Six failing text colours moved to the nearest AA lightness, with hue and chroma held
Text on backgroundBeforeAfter (AA)Lightness changeDetails
#51A2FF on #FFFFFFoklch(0.704 0.158 253.6) · 2.63:1oklch(0.544 0.158 253.6) · #1870C8 · 5.01:1−0.16 LPair page
#FE9A00 on #FFFFFFoklch(0.772 0.173 65.4) · 2.13:1oklch(0.572 0.173 65.4) · #BA5B00 · 4.58:1−0.20 LPair page
#00C950 on #FFFFFFoklch(0.729 0.212 147.8) · 2.21:1oklch(0.529 0.212 147.8) · #008900 · 4.58:1−0.20 LPair page
#FF6467 on #FFFFFFoklch(0.702 0.189 22.2) · 2.88:1oklch(0.582 0.189 22.2) · #D43B44 · 4.65:1−0.12 LPair page
#155DFC on #000000oklch(0.547 0.246 262.9) · 4.00:1oklch(0.587 0.246 262.9) · #236BFF · 4.61:1+0.04 LPair page
#5B8DEF on #F5F5F5oklch(0.655 0.156 262.5) · 2.96:1oklch(0.535 0.156 262.5) · #3968C6 · 4.85:1−0.12 LOpen the checker

Two things stand out. First, the size of the change varies a lot: a pair that is a little short needs a small move and a very light colour needs a large one. Second, the fix can go in either direction. The blue on black row needed a slightly lighter text colour, because on a dark background more contrast comes from more lightness.

When changing lightness is not enough

Sometimes no lightness works. If the background is a mid-tone, neither very light nor very dark text may reach 4.5:1 against it, and the Fix will report that no passing lightness was found. In that case, change the background instead, or use a different surface for the text. The same logic applies to the pair page, which offers both a text fix and a background fix.

  • Large text. If the text is at least 18 point regular or 14 point bold, the target drops to 3:1, which may need no change at all. Do not rely on this for body copy.
  • Non-text parts. Borders, icons and focus rings need 3:1 against their surroundings, a different check from the text one.
  • Gradients and images. Test the worst spot behind the text, not the average.
  • Gamut. Dark, saturated colours may sit outside sRGB after the move. The fix then reduces chroma just enough to fit, so the hex can differ slightly from the OKLCH value.

How the checker applies this

The contrast checker uses exactly the method above. You enter a text and a background colour, it shows the WCAG ratio and the APCA Lc score, and when the pair fails it proposes the nearest passing lightness for the text, with hue and chroma unchanged. Common pairs also have static pages under contrast fix pairs, which list a text fix and a background fix for both the AA and AAA targets.

If you fix one colour, fix the family. Rather than patching every failing component, build the scale once with a sensible lightness progression, which is covered in the guide to accessible colour palettes.

FAQ

How do I fix colour contrast without changing the brand colour?
Keep the hue and chroma and change only the lightness. In OKLCH, moving lightness darker or lighter until the ratio clears 4.5:1 gives the nearest passing colour, which still reads as the same colour family.
Should I fix the text or the background?
Usually the text, because it is a smaller change. Change the background when the text colour is fixed, for example a brand colour, or when the background is a mid-tone that no neutral text can pass against.
What if the Fix says no passing lightness exists?
Then the background is too close to the middle of the lightness range for this hue and chroma. Change the background, switch to white or black text, or reduce chroma. Large text has a lower 3:1 target, which can help for headings.
Does a fix change the hue?
No. Hue and chroma stay as they were. The only exception is a colour outside the sRGB gamut after the lightness change, where chroma is reduced slightly so the hex value is displayable.
Is passing WCAG AA enough for readable text?
AA is the standard audits use and a good minimum, but thin or small text can still be hard to read at 4.5:1. If readability matters more than compliance, aim higher than the minimum and check the APCA Lc value as a second opinion.

Try it

Paste your text and background colours, see whether they pass, and apply the lightness fix in one click.

Fix a colour pair

← All guides