Bottom-line: I made gradient headlines pass WCAG without turning them into flat gray text by testing the palest stop first, darkening only what failed, and shipping a solid fallback from the darkest stop. If you build display copy with the free CSS gradient text generator and verify every pairing in the color contrast checker, you can keep vibrant blends for heroes while holding 4.5 to 1 for body and 3 to 1 for large headlines.
I learned this the hard way on a SaaS launch hero last month when a sunset blend looked electric on my calibrated monitor and died on a budget laptop over white. The endpoints were rich plum and deep coral that both passed easily, but the peachy midpoint vanished into the background.
What Ratio Gradient Text Must Pass for Body and Headlines
Gradient text does not get its own special WCAG number. Each visible letter is still text over a background, so the same WCAG 2.2 contrast minimums apply stop by stop. For normal body copy under roughly 24px regular or 19px bold, you must clear 4.5 to 1 against the page background. For large-scale text at or above those sizes, especially at 700 weight and above, the floor drops to 3 to 1.
The trap with clipped text gradients is that the ratio changes across the width of a single word. A violet endpoint at #764ba2 on white near 7.1 to 1 can sit beside a pale yellow midpoint at #f9d423 on white near 1.4 to 1 inside the same headline.
| Text use | Minimum ratio | Size and weight rule | Gradient implication |
|---|---|---|---|
| Body and supporting sentences | 4.5 to 1 | Below 24px regular or 19px bold | Every stop plus visual midpoint must pass, no pale pastels |
| Large headlines and hero accents | 3 to 1 | 24px plus regular or 19px plus bold | Lightest stop may use 3 to 1 only at true large bold size |
| Enhanced long-form reading | 7 to 1 | Articles and docs | Prefer solid text, reserve gradient for short display words |
| Focus rings near gradient buttons | 3 to 1 | All weights | Ring must contrast against gradient fill and page canvas |
| Decorative numerals only | Exempt if non-essential | Large display | Mark as aria-hidden when duplicate solid text exists |
- 4.5 to 1 is the non-negotiable floor for any gradient text under large size.
- 3 to 1 applies only to genuinely large bold display type at final rendered size.
- Lightest stop governs the whole headline, not the average or darkest edge.
- Checker plus canvas toggles beat page-level scanners for clipped text.
- One step darker than passing is my shipping rule for sunlight safety.
How to Test the Lightest Stop Against Your Background
My repeatable method starts before I open the checker. I list every hex in the gradient bar with its percent, then note the exact page background including section washes, cards, and any image scrim at real opacity. I toggle the generator preview across light canvas white, dark #111827, and checker transparency because the same Ocean fade that hits 12.3 to 1 on dark can fall to 1.9 to 1 on white.
A five-minute lightest-stop checklist I use on every hero
I keep this on a sticky note because it prevents optimistic testing. Identify the palest swatch visually, confirm with lightness values, test it alone, then test neighbors within 20 percent distance on the bar.
- Eyedropper the palest stop first, not the brand primary endpoint.
- Test at true px and weight such as 72px 800 for heroes, not default 16px 400.
- Test light plus dark plus image canvases before claiming a pass.
- Log every ratio with hex, background, size, and theme for regression checks.
How to Darken Stops and Add a Via Midpoint That Passes
Darkening is surgery, not a dimmer switch. When a light stop fails, I deepen only that stop by 15 to 25 lightness points in HSL while holding hue, then retest. For a failing #f9d423 yellow near 1.4 to 1 on white I shift toward #b45309 amber until it clears 3 to 1 for large or 4.5 to 1 for body-adjacent use. I avoid adding text-shadow to fake contrast because shadows muddy clipped edges.
| Failure I see | What to change | Example fix I shipped | Retest target |
|---|---|---|---|
| Pale yellow midpoint on white near 1.4 to 1 | Darken to amber plus add via at 50 percent | #f9d423 to #b45309 via at 55 percent | 3 to 1 large or 4.5 to 1 body |
| Light cyan on white near 1.9 to 1 | Deepen cyan or restrict to dark canvas | #00f2fe to #0e7490 for light theme | 4.5 to 1 if under 24px |
| Soft pink on white near 2.1 to 1 | Insert darker via plus raise to 800 weight | Add #be185d via between pinks | 3 to 1 at 72px 800 |
| Silver #ebedee on white near 1.2 to 1 | Reserve for dark heroes only | Kept #ebedee endpoint on #111827 at 12 plus to 1 | Pass AAA on dark only |
| Sunset orange #ff512f on white at 3.4 to 1 | Keep for large only, darken for small | Used at 72px 800, solid #9a3412 for eyebrows |
- Darken failing lights only by 15 to 25 points, keep passing darks intact.
- Add a darker via at 50 percent when endpoints are locked by brand.
- Bump to 700 plus weight for large claims and 800 for heroes.
- Retest every theme after each tweak, light plus dark plus scrim.
Fallback Color Pattern That Keeps Text Readable Everywhere
Clipped gradient text depends on clipped background plus transparent fill, which Windows High Contrast, very old browsers, and some print paths ignore. Without a fallback those users see invisible or solid black letters. My pattern sets a solid color first using the darkest passing stop, then overrides with gradient inside an enhancement block.
.hero-grad { color: #764ba2; background: linear-gradient(90deg, #667eea 0%, #764ba2 50%, #f093fb 100%); }
High Contrast and reduced-transparency notes I verify
I test with forced-colors active and with background images disabled. The solid fallback must itself pass 4.5 to 1 or 3 to 1 as appropriate, not merely look close. I keep focus-visible outlines at 3 to 1 against both gradient and fallback so keyboard users never lose position.
Large Headline Exceptions and When 3 to 1 Is Enough
The large-text allowance is narrow and often misused. It applies only when text renders at roughly 18pt regular near 24px or 14pt bold near 19px bold and above at final CSS size. A 32px hero at 800 weight qualifies.
- 72px to 96px heroes at 800 weight can responsibly target 3 to 1 on palest stop.
- Eyebrows at 12px to 14px uppercase never qualify, even at 800 weight.
- Button labels and nav links need 4.5 to 1 because they function as body-size UI.
Next Steps to Master the L1 Generator and Contrast Guide
You now have the contrast proof loop. Return to the parent L1 CSS Gradient Text Generator guide with Ocean and Violet ramp tests at 72px 800 weight. Then deepen your system with the sibling color palette and contrast accessibility guide for harmony ramps and token governance.
My shipping order is simple. Draft the headline in the generator with two to three stops at 90 degrees, test palest stop first for 4.5 to 1 or 3 to 1 as size dictates, darken or add via until it clears with margin, set solid fallback from darkest stop, and snapshot both themes.