Skip to content
ChromaBrew
Go Pro
AccessibilityBy Opeyemi Olorunfemi

Accessible gradients: contrast rules for real interfaces

WCAG has no gradient formula, so text over a gradient needs a strategy: check the worst stop, lay a scrim, keep button labels on a solid band, and always provide a fallback color.

There is no WCAG gradient algorithm

Contrast ratios are defined between two solid colors, and a gradient is a continuum. The spec gives no single number, so the correct approach is to treat the range as a worst-case problem: the text must pass against the least favourable stop it crosses. If a label sits on a gradient, the stop with the closest luminance to the text decides whether the pair ships.

That one rule explains most gradient accessibility failures: a headline passes on the bright half and dies over the saturated dark half of the same banner.

Tip

Extract the gradient's extreme stops and test text against the darkest (for light text) and lightest (for dark text). If the worst stop fails, the gradient fails.

Scrims: gradient is on the background, not the text

The most reliable pattern for text over imagery or wide gradients is a scrim — a translucent gradient layer between the art and the text. You control the text/background relationship by the scrim's opacity and direction (dark at the bottom where the label sits, fading to transparent above). The text then grades against a raised dark band rather than a moving target.

The same trick works for button labels: instead of hoping the brand shimmer covers contrast, give the control a solid label token on top and let the gradient live in the fill. The label runs against a uniform swatch, and the gradient is decoration the ratio never sees.

.hero {
  background:
    linear-gradient(to top, rgba(10, 8, 20, 0.82), rgba(10, 8, 20, 0) 60%);
}
.hero__title {
  /* light text now sits on a near-solid dark band */
  color: oklch(0.97 0 0);
}

Always ship a solid fallback

Gradients are progressive enhancement. Before the gradient rule, declare a solid background using the gradient's dominant or darkest color — browsers that support it paint over the fallback, older ones still get a readable base. The fallback rule comes first so the cascade does the upgrade.

A two-line rule costs nothing and removes the entire class of 'empty background' failures in legacy environments.

.hero {
  background: #13101e; /* fallback for no-gradient engines */
  background: linear-gradient(135deg, #6d28d9, #13101e);
}

Keep interactive gradients honest

A gradient button behind text is a contrast bug waiting to land. The safest pattern is a flat fill for the control itself and gradient reserved for decorative areas with no text dependency — or a gradient fill whose endpoints both pass the label's ratio. When you do want a lively button, check both endpoints and the midpoint separately, because hue rotation mid-gradient can drop chroma and eat contrast in the middle.

Related free tools

Want to apply this right now? Open the color palette generator and try it with your own brand color — free, no sign-up.