Home / Articles / Color /

color

Gradient text with background-clip

The background-clip: text technique turns any CSS gradient into text fill. It's visually striking — and has accessibility traps worth knowing about.

The three-property recipe

Gradient text requires three declarations working together. Remove any one and the effect breaks.

.gradient-heading {
  background: linear-gradient(135deg, oklch(0.72 0.19 265), oklch(0.68 0.22 310));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
  • background — defines the gradient that will fill the text. Without it, there's nothing to clip.
  • background-clip: text — clips the background to the text glyphs instead of the element's padding box. The -webkit- prefix is still needed for Safari.
  • color: transparent — makes the text's own fill invisible, revealing the gradient behind it. Without this, the solid text color paints on top and hides the gradient.

Building the gradient

Any valid CSS gradient works as the background — linear-gradient, radial-gradient, conic-gradient, or even layered combinations. The angle and color stops control the visual direction.

/* horizontal sweep */
background: linear-gradient(90deg, oklch(0.72 0.19 265), oklch(0.68 0.22 310));

/* diagonal with three stops */
background: linear-gradient(
  135deg,
  oklch(0.7 0.2 280),
  oklch(0.65 0.22 310) 50%,
  oklch(0.7 0.18 340)
);

/* radial — glows from center */
background: radial-gradient(circle at 30% 50%, oklch(0.72 0.2 265), oklch(0.6 0.18 310));

For readability on dark backgrounds, keep all gradient stops above 0.6 lightness in oklch. Dipping below that makes portions of the text hard to read.

Animated gradient text

You can animate the gradient position to create a shimmer or color-cycling effect. The trick is to size the background larger than the element, then animate background-position.

.shimmer-text {
  background: linear-gradient(
    90deg,
    oklch(0.72 0.19 265),
    oklch(0.68 0.22 310),
    oklch(0.72 0.19 265)
  );
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: shimmer 3s ease-in-out infinite;
}

@keyframes shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

Be aware that background-position animates on the main thread, not the compositor. Keep these animations on headings (small paint area) and avoid applying them to large text blocks or many elements simultaneously.

The accessibility problem

Setting color: transparent removes the text's solid fill. In Windows High Contrast Mode (forced-colors), the browser overrides backgrounds but not text color — resulting in invisible text against the forced background. This is a real failure mode, not a theoretical concern.

@media (forced-colors: active) {
  .gradient-heading {
    background: none;
    -webkit-background-clip: border-box;
    background-clip: border-box;
    color: CanvasText; /* system text color */
  }
}

The forced-colors media query is supported in Chrome 89+, Edge 79+, Firefox 89+. Safari does not implement forced-colors but also does not have a high-contrast mode that triggers this failure.

Beyond forced-colors, verify that every point along the gradient meets WCAG contrast requirements against the background. A gradient that fades from bright to dim may pass at one end and fail at the other.

Fallback for older browsers

Use @supports to progressively enhance. Without support, text stays its normal solid color — a perfectly acceptable fallback.

.gradient-heading {
  color: oklch(0.72 0.19 265); /* fallback: solid accent color */
}

@supports (-webkit-background-clip: text) or (background-clip: text) {
  .gradient-heading {
    background: linear-gradient(135deg, oklch(0.72 0.19 265), oklch(0.68 0.22 310));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

The fallback color should match one of the gradient's stops so the design intent is preserved even without the gradient effect.

When to use gradient text

Gradient text works best on large, bold headings and hero text where the gradient has room to be visible. It fails on body copy — the gradient is imperceptible at small sizes, and the accessibility concerns multiply across paragraphs of text.

  • Limit to 1–2 gradient text elements per page. More than that dilutes the visual impact.
  • Use bold or heavy font weights. Thin fonts don't show enough gradient surface area.
  • Stick to high-contrast gradients on dark backgrounds — both stops above 0.6 lightness in oklch.
  • Never use gradient text on interactive elements like links or buttons where the text color carries semantic meaning (visited, active, disabled).

Practical strategy for 2026

background-clip: text works unprefixed in Chrome 120+, Firefox 49+. Safari still requires the -webkit- prefix as of Safari 18. Always include both the prefixed and unprefixed declarations. The technique is Baseline widely available.

Always include the forced-colors fallback and the @supports wrapper. The visual effect is decorative — it should degrade to a solid color without breaking the reading experience.