Every image hero faces the same physics: photos have bright spots, text needs contrast, and the CMS means you don't control which photo ships next quarter. The lazy fix is a 50% black overlay across the whole image — readable text, murdered photo. The craft fix is the scrim: darkness only where the text lives, fading to nothing where the image does its job.
Velocity X's hero-background-scrim packages the pattern; the gradient recipe is worth understanding even if you never install it.
The Money Pattern
<section class="relative">
<img src={hero.src} alt="" class="absolute inset-0 h-full w-full object-cover" />
<!-- The scrim: eased multi-stop, bottom-anchored where the text sits -->
<div class="absolute inset-0 bg-gradient-to-t
from-black/70 via-black/35 via-40% to-transparent to-75%" />
<div class="relative px-6 pb-14 pt-40 text-white">
<h1 class="text-5xl font-semibold">{hero.title}</h1>
<p class="mt-3 max-w-xl text-white/85">{hero.sub}</p>
</div>
</section>
The multi-stop matters: a naive two-stop from-black to-transparent has a visible hard band where the gradient ends — the "scrim line" you've seen on a thousand news sites. Stacking intermediate stops (70 → 35 → 0) approximates an eased curve and the edge disappears. Text sits in the dense zone; the image's top two-thirds stays untouched.
The Catch
The scrim must survive the worst-case photo, not the one in the design file. The test: swap in a white wall and a night shot — if the headline passes contrast on both, the scrim is doing its job. If your imagery is editor-controlled chaos, add text-shadow as the second line of defence; it's unfashionable and it works.
Two implementation notes: the decorative hero image gets alt="" (the headline is the content — a screen reader doesn't need "photo of roof" before it), and the scrim div takes pointer-events-none if anything interactive sits under it... but nothing interactive should sit under a scrim, because a darkened button is a disabled-looking button.
The Verdict
Scrim where the text is, image everywhere else, eased stops so there's no band, tested against photos you don't control. It's in Velocity X's Heroes & Sections — pure Astro, zero JS, like a hero backdrop should be.









