Pure TailwindMIT licensed

Tailwind Gradient Text Fallback with @supports

A three-layer progressive-enhancement reference in pure utilities. Layer 1 is a solid colour every browser renders; layer 2 adds the gradient only inside supports-[background-clip:text]:; layer 3 shows the complete pattern with a not-supports-[…]: underline as a designed fallback — so no engine ever shows invisible text.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<section class="ttg-17 w-full min-h-svh grid place-items-start justify-center bg-ttg17-bg px-5 py-14 font-ttg17-sans text-ttg17-ink" aria-labelledby="ttg17-title">
  <div class="w-full max-w-2xl">
    <h2 id="ttg17-title" class="text-[28px] font-extrabold tracking-[-0.025em]">Gradient text that never disappears</h2>
    <p class="mt-2 max-w-xl text-[15px]/[1.7] text-ttg17-mut text-pretty">A layered fallback: modern engines get the gradient, everything else gets readable solid colour — no JavaScript.</p>
    <ol class="mt-8 grid gap-4">
      <li class="grid gap-4 rounded-2xl border border-ttg17-line bg-white p-5 shadow-[0_1px_2px_rgb(0_0_0/0.04)] sm:grid-cols-[auto_1fr]">
        <span class="grid size-9 place-items-center rounded-lg bg-ttg17-l1 font-ttg17-mono text-sm font-medium text-ttg17-l1-ink">1</span>
        <div>
          <h3 class="font-semibold">Solid colour first</h3>
          <p class="mt-1 text-sm/[1.6] text-ttg17-mut">Every browser renders a plain <code class="font-ttg17-mono text-[12.5px] text-ttg17-b">text-*</code> colour.</p>
          <p class="mt-3 text-[34px] leading-tight font-extrabold tracking-tight text-ttg17-a">Solid fallback</p>
          <pre class="mt-3 overflow-x-auto rounded-lg bg-ttg17-code px-3.5 py-2.5 font-ttg17-mono text-[12px] text-ttg17-code-ink">text-ttg17-a</pre>
        </div>
      </li>
      <li class="grid gap-4 rounded-2xl border border-ttg17-line bg-white p-5 shadow-[0_1px_2px_rgb(0_0_0/0.04)] sm:grid-cols-[auto_1fr]">
        <span class="grid size-9 place-items-center rounded-lg bg-ttg17-l2 font-ttg17-mono text-sm font-medium text-ttg17-l2-ink">2</span>
        <div>
          <h3 class="font-semibold">Guard the gradient</h3>
          <p class="mt-1 text-sm/[1.6] text-ttg17-mut">Clip and transparency only apply inside <code class="font-ttg17-mono text-[12.5px] text-ttg17-b">supports-[background-clip:text]:</code>.</p>
          <p class="mt-3 w-fit text-[34px] leading-tight font-extrabold tracking-tight text-ttg17-a supports-[background-clip:text]:bg-linear-to-r supports-[background-clip:text]:from-ttg17-a supports-[background-clip:text]:to-ttg17-b supports-[background-clip:text]:bg-clip-text supports-[background-clip:text]:text-transparent">Guarded gradient</p>
          <pre class="mt-3 overflow-x-auto rounded-lg bg-ttg17-code px-3.5 py-2.5 font-ttg17-mono text-[12px] text-ttg17-code-ink">supports-[background-clip:text]:bg-clip-text
supports-[background-clip:text]:text-transparent</pre>
        </div>
      </li>
      <li class="grid gap-4 rounded-2xl border border-ttg17-line bg-white p-5 shadow-[0_1px_2px_rgb(0_0_0/0.04)] sm:grid-cols-[auto_1fr]">
        <span class="grid size-9 place-items-center rounded-lg bg-ttg17-l3 font-ttg17-mono text-sm font-medium text-ttg17-l3-ink">3</span>
        <div>
          <h3 class="font-semibold">Design the fallback</h3>
          <p class="mt-1 text-sm/[1.6] text-ttg17-mut">Unsupported engines get a deliberate underline accent via <code class="font-ttg17-mono text-[12.5px] text-ttg17-b">not-supports-[…]:</code>.</p>
          <p class="mt-3 w-fit text-[34px] leading-tight font-extrabold tracking-tight text-ttg17-a decoration-ttg17-b decoration-4 underline-offset-8 not-supports-[background-clip:text]:underline supports-[background-clip:text]:bg-linear-to-r supports-[background-clip:text]:from-ttg17-a supports-[background-clip:text]:to-ttg17-b supports-[background-clip:text]:bg-clip-text supports-[background-clip:text]:text-transparent">Final output</p>
          <pre class="mt-3 overflow-x-auto rounded-lg bg-ttg17-code px-3.5 py-2.5 font-ttg17-mono text-[12px] text-ttg17-code-ink">not-supports-[background-clip:text]:underline</pre>
        </div>
      </li>
    </ol>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-ttg17-bg: #f6f8fb;
  --color-ttg17-bg: oklch(0.977 0.005 255);
  --color-ttg17-ink: #0f172a;
  --color-ttg17-ink: oklch(0.21 0.04 265);
  --color-ttg17-mut: #525c6e;
  --color-ttg17-mut: oklch(0.47 0.03 260);
  --color-ttg17-line: #e2e7ef;
  --color-ttg17-line: oklch(0.925 0.01 260);
  --color-ttg17-code: #0f172a;
  --color-ttg17-code: oklch(0.21 0.04 265);
  --color-ttg17-code-ink: #cdd6f4;
  --color-ttg17-code-ink: oklch(0.88 0.04 275);
  --color-ttg17-a: #2257e0;
  --color-ttg17-a: oklch(0.52 0.21 264);
  --color-ttg17-b: #d42b84;
  --color-ttg17-b: oklch(0.58 0.22 355);
  --color-ttg17-l1: #fef3c7;
  --color-ttg17-l1: oklch(0.96 0.06 95);
  --color-ttg17-l1-ink: #854d0e;
  --color-ttg17-l1-ink: oklch(0.47 0.11 65);
  --color-ttg17-l2: #dbeafe;
  --color-ttg17-l2: oklch(0.93 0.04 255);
  --color-ttg17-l2-ink: #1e40af;
  --color-ttg17-l2-ink: oklch(0.42 0.18 265);
  --color-ttg17-l3: #fce7f3;
  --color-ttg17-l3: oklch(0.94 0.035 350);
  --color-ttg17-l3-ink: #9d174d;
  --color-ttg17-l3-ink: oklch(0.45 0.17 0);
  --font-ttg17-sans: 'Geist', system-ui, sans-serif;
  --font-ttg17-mono: 'Geist Mono', ui-monospace, monospace;
}

.ttg-17 {
  width: 100%;
  min-height: 100svh;
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

Compiles in the browser — perfect for a CodePen or a quick test, not for production.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --color-ttg17-bg: #f6f8fb;
  --color-ttg17-bg: oklch(0.977 0.005 255);
  --color-ttg17-ink: #0f172a;
  --color-ttg17-ink: oklch(0.21 0.04 265);
  --color-ttg17-mut: #525c6e;
  --color-ttg17-mut: oklch(0.47 0.03 260);
  --color-ttg17-line: #e2e7ef;
  --color-ttg17-line: oklch(0.925 0.01 260);
  --color-ttg17-code: #0f172a;
  --color-ttg17-code: oklch(0.21 0.04 265);
  --color-ttg17-code-ink: #cdd6f4;
  --color-ttg17-code-ink: oklch(0.88 0.04 275);
  --color-ttg17-a: #2257e0;
  --color-ttg17-a: oklch(0.52 0.21 264);
  --color-ttg17-b: #d42b84;
  --color-ttg17-b: oklch(0.58 0.22 355);
  --color-ttg17-l1: #fef3c7;
  --color-ttg17-l1: oklch(0.96 0.06 95);
  --color-ttg17-l1-ink: #854d0e;
  --color-ttg17-l1-ink: oklch(0.47 0.11 65);
  --color-ttg17-l2: #dbeafe;
  --color-ttg17-l2: oklch(0.93 0.04 255);
  --color-ttg17-l2-ink: #1e40af;
  --color-ttg17-l2-ink: oklch(0.42 0.18 265);
  --color-ttg17-l3: #fce7f3;
  --color-ttg17-l3: oklch(0.94 0.035 350);
  --color-ttg17-l3-ink: #9d174d;
  --color-ttg17-l3-ink: oklch(0.45 0.17 0);
  --font-ttg17-sans: 'Geist', system-ui, sans-serif;
  --font-ttg17-mono: 'Geist Mono', ui-monospace, monospace;
}

.ttg-17 {
  width: 100%;
  min-height: 100svh;
}
3Fonts used by this demooptional — skip if you have your own type stack
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist:wght@400..800&family=Geist+Mono:wght@400;500&display=swap">

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • Two hand-written @supports blocks became supports-[background-clip:text]: variants on the elements they change.
  • UI upgrade: layer 3 now designs the fallback with not-supports-[…]:underline, instead of repeating layer 2.
  • UI upgrade: an ordered list with numbered layer badges and a dark code block per layer, so the reference doubles as copy-paste documentation.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Gradient Text Fallback with @supports
Source: https://codefronts.com/motion/tailwind-css-text-gradient/tailwind-gradient-text-fallback-with-supports/

A three-layer progressive-enhancement reference in pure utilities. Layer 1 is a solid colour every browser renders; layer 2 adds the gradient only inside supports-[background-clip:text]:; layer 3 shows the complete pattern with a not-supports-[…]: underline as a designed fallback &mdash; so no engine ever shows invisible text.
## HTML
```html
<section class="ttg-17 w-full min-h-svh grid place-items-start justify-center bg-ttg17-bg px-5 py-14 font-ttg17-sans text-ttg17-ink" aria-labelledby="ttg17-title">
  <div class="w-full max-w-2xl">
    <h2 id="ttg17-title" class="text-[28px] font-extrabold tracking-[-0.025em]">Gradient text that never disappears</h2>
    <p class="mt-2 max-w-xl text-[15px]/[1.7] text-ttg17-mut text-pretty">A layered fallback: modern engines get the gradient, everything else gets readable solid colour — no JavaScript.</p>
    <ol class="mt-8 grid gap-4">
      <li class="grid gap-4 rounded-2xl border border-ttg17-line bg-white p-5 shadow-[0_1px_2px_rgb(0_0_0/0.04)] sm:grid-cols-[auto_1fr]">
        <span class="grid size-9 place-items-center rounded-lg bg-ttg17-l1 font-ttg17-mono text-sm font-medium text-ttg17-l1-ink">1</span>
        <div>
          <h3 class="font-semibold">Solid colour first</h3>
          <p class="mt-1 text-sm/[1.6] text-ttg17-mut">Every browser renders a plain <code class="font-ttg17-mono text-[12.5px] text-ttg17-b">text-*</code> colour.</p>
          <p class="mt-3 text-[34px] leading-tight font-extrabold tracking-tight text-ttg17-a">Solid fallback</p>
          <pre class="mt-3 overflow-x-auto rounded-lg bg-ttg17-code px-3.5 py-2.5 font-ttg17-mono text-[12px] text-ttg17-code-ink">text-ttg17-a</pre>
        </div>
      </li>
      <li class="grid gap-4 rounded-2xl border border-ttg17-line bg-white p-5 shadow-[0_1px_2px_rgb(0_0_0/0.04)] sm:grid-cols-[auto_1fr]">
        <span class="grid size-9 place-items-center rounded-lg bg-ttg17-l2 font-ttg17-mono text-sm font-medium text-ttg17-l2-ink">2</span>
        <div>
          <h3 class="font-semibold">Guard the gradient</h3>
          <p class="mt-1 text-sm/[1.6] text-ttg17-mut">Clip and transparency only apply inside <code class="font-ttg17-mono text-[12.5px] text-ttg17-b">supports-[background-clip:text]:</code>.</p>
          <p class="mt-3 w-fit text-[34px] leading-tight font-extrabold tracking-tight text-ttg17-a supports-[background-clip:text]:bg-linear-to-r supports-[background-clip:text]:from-ttg17-a supports-[background-clip:text]:to-ttg17-b supports-[background-clip:text]:bg-clip-text supports-[background-clip:text]:text-transparent">Guarded gradient</p>
          <pre class="mt-3 overflow-x-auto rounded-lg bg-ttg17-code px-3.5 py-2.5 font-ttg17-mono text-[12px] text-ttg17-code-ink">supports-[background-clip:text]:bg-clip-text
supports-[background-clip:text]:text-transparent</pre>
        </div>
      </li>
      <li class="grid gap-4 rounded-2xl border border-ttg17-line bg-white p-5 shadow-[0_1px_2px_rgb(0_0_0/0.04)] sm:grid-cols-[auto_1fr]">
        <span class="grid size-9 place-items-center rounded-lg bg-ttg17-l3 font-ttg17-mono text-sm font-medium text-ttg17-l3-ink">3</span>
        <div>
          <h3 class="font-semibold">Design the fallback</h3>
          <p class="mt-1 text-sm/[1.6] text-ttg17-mut">Unsupported engines get a deliberate underline accent via <code class="font-ttg17-mono text-[12.5px] text-ttg17-b">not-supports-[…]:</code>.</p>
          <p class="mt-3 w-fit text-[34px] leading-tight font-extrabold tracking-tight text-ttg17-a decoration-ttg17-b decoration-4 underline-offset-8 not-supports-[background-clip:text]:underline supports-[background-clip:text]:bg-linear-to-r supports-[background-clip:text]:from-ttg17-a supports-[background-clip:text]:to-ttg17-b supports-[background-clip:text]:bg-clip-text supports-[background-clip:text]:text-transparent">Final output</p>
          <pre class="mt-3 overflow-x-auto rounded-lg bg-ttg17-code px-3.5 py-2.5 font-ttg17-mono text-[12px] text-ttg17-code-ink">not-supports-[background-clip:text]:underline</pre>
        </div>
      </li>
    </ol>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-ttg17-bg: #f6f8fb;
  --color-ttg17-bg: oklch(0.977 0.005 255);
  --color-ttg17-ink: #0f172a;
  --color-ttg17-ink: oklch(0.21 0.04 265);
  --color-ttg17-mut: #525c6e;
  --color-ttg17-mut: oklch(0.47 0.03 260);
  --color-ttg17-line: #e2e7ef;
  --color-ttg17-line: oklch(0.925 0.01 260);
  --color-ttg17-code: #0f172a;
  --color-ttg17-code: oklch(0.21 0.04 265);
  --color-ttg17-code-ink: #cdd6f4;
  --color-ttg17-code-ink: oklch(0.88 0.04 275);
  --color-ttg17-a: #2257e0;
  --color-ttg17-a: oklch(0.52 0.21 264);
  --color-ttg17-b: #d42b84;
  --color-ttg17-b: oklch(0.58 0.22 355);
  --color-ttg17-l1: #fef3c7;
  --color-ttg17-l1: oklch(0.96 0.06 95);
  --color-ttg17-l1-ink: #854d0e;
  --color-ttg17-l1-ink: oklch(0.47 0.11 65);
  --color-ttg17-l2: #dbeafe;
  --color-ttg17-l2: oklch(0.93 0.04 255);
  --color-ttg17-l2-ink: #1e40af;
  --color-ttg17-l2-ink: oklch(0.42 0.18 265);
  --color-ttg17-l3: #fce7f3;
  --color-ttg17-l3: oklch(0.94 0.035 350);
  --color-ttg17-l3-ink: #9d174d;
  --color-ttg17-l3-ink: oklch(0.45 0.17 0);
  --font-ttg17-sans: 'Geist', system-ui, sans-serif;
  --font-ttg17-mono: 'Geist Mono', ui-monospace, monospace;
}

.ttg-17 {
  width: 100%;
  min-height: 100svh;
}
```

How this works

The failure mode is invisible text. If an engine accepts color: transparent but not background-clip: text, the gradient paints as a rectangle and the letters vanish. The guard makes transparency conditional:

<span class="text-ttg17-a
  supports-[background-clip:text]:bg-linear-to-r
  supports-[background-clip:text]:from-ttg17-a
  supports-[background-clip:text]:to-ttg17-b
  supports-[background-clip:text]:bg-clip-text
  supports-[background-clip:text]:text-transparent">

The variant is @supports. supports-[background-clip:text]: compiles to @supports (background-clip:text); not-supports-[…]: compiles to @supports not (…), letting you design the fallback rather than merely tolerate it.

Make it yours

  • Test the fallback: temporarily change the guard to supports-[background-clip:nonsense]:.
  • Bolder fallback: use not-supports-[…]:font-black or a tinted bg- highlight instead of underline.
  • Component: wrap the long class list in a @utility text-gradient in your own CSS once you've settled on it.
  • Prefix-only engines: guard with supports-[-webkit-background-clip:text]: as well.

Gotchas — read before shipping

  • Any engine that runs Tailwind v4's sheet already supports clipping — the guard matters most for HTML email, embedded WebViews and the CDN fallback stylesheet you ship to old clients.
  • Don't put CSS variables inside the supports-[…] condition; it tests the literal declaration.
  • The fallback colour should be the gradient's darkest stop so contrast holds in both states.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

@supports is universal; the pattern's value is in the rendered fallback for clients that don't run the full sheet.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Search CodeFronts

Loading…