31 CSS Hero Sections20 / 31
Gradient Text Spotlight
Oversized headline with an animated marigold → ruby → grape gradient sweeping across the letters. The Linear / Apple wordmark shimmer treatment.
Published
The code
<section class="hs-20" aria-label="Hero">
<div class="hs-20__inner">
<span class="hs-20__eye">v3 launching tuesday</span>
<h2>Made for the way <span class="hs-20__shine">creative people</span> actually work.</h2>
<p>One canvas. Every layer. Zero exporting between apps to nudge a kerning pair.</p>
<a class="hs-20__cta" href="#waitlist">Join the waitlist →</a>
</div>
</section><section class="hs-20" aria-label="Hero">
<div class="hs-20__inner">
<span class="hs-20__eye">v3 launching tuesday</span>
<h2>Made for the way <span class="hs-20__shine">creative people</span> actually work.</h2>
<p>One canvas. Every layer. Zero exporting between apps to nudge a kerning pair.</p>
<a class="hs-20__cta" href="#waitlist">Join the waitlist →</a>
</div>
</section>.hs-20 {
display: grid;
place-items: center;
width: 100%;
min-height: 100vh;
padding: clamp(28px, 5vw, 64px) clamp(20px, 5vw, 56px);
background: radial-gradient(60% 60% at 50% 0%, rgba(120,30,90,0.18), transparent 70%), #1a0d20;
font-family: 'Inter', system-ui, sans-serif;
color: #f4e8d0;
box-sizing: border-box;
}
.hs-20__inner {
max-width: 720px;
text-align: center;
}
.hs-20__eye {
display: inline-block;
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
letter-spacing: 0.16em;
color: #f5b148;
padding: 4px 10px;
border: 1px solid rgba(245,177,72,0.4);
border-radius: 999px;
margin-bottom: 22px;
}
.hs-20 h2 {
margin: 0 0 18px;
font-size: clamp(38px, 6vw, 68px);
font-weight: 800;
letter-spacing: -0.025em;
line-height: 1.05;
}
.hs-20__shine {
display: inline-block;
background: linear-gradient(90deg, #f5b148, #d63a5e, #7e2d8a, #f5b148);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: hs-20-sweep 4s linear infinite;
}
@keyframes hs-20-sweep {
to {
background-position: 200% 0;
}
}
.hs-20 p {
margin: 0 auto 26px;
font-size: 17px;
line-height: 1.55;
color: #b8a890;
max-width: 460px;
}
.hs-20__cta {
display: inline-block;
padding: 13px 26px;
background: linear-gradient(90deg, #f5b148, #d63a5e);
color: #1a0d20;
border-radius: 999px;
text-decoration: none;
font-weight: 700;
font-size: 14.5px;
box-shadow: 0 12px 30px rgba(214,58,94,0.35);
transition: transform 0.15s;
}
.hs-20__cta:hover {
transform: translateY(-1px);
}
@media (prefers-reduced-motion: reduce) {
.hs-20__shine {
animation: none;
background-position: 0 0;
}
.hs-20__cta {
transition: none;
}
}.hs-20 {
display: grid;
place-items: center;
width: 100%;
min-height: 100vh;
padding: clamp(28px, 5vw, 64px) clamp(20px, 5vw, 56px);
background: radial-gradient(60% 60% at 50% 0%, rgba(120,30,90,0.18), transparent 70%), #1a0d20;
font-family: 'Inter', system-ui, sans-serif;
color: #f4e8d0;
box-sizing: border-box;
}
.hs-20__inner {
max-width: 720px;
text-align: center;
}
.hs-20__eye {
display: inline-block;
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
letter-spacing: 0.16em;
color: #f5b148;
padding: 4px 10px;
border: 1px solid rgba(245,177,72,0.4);
border-radius: 999px;
margin-bottom: 22px;
}
.hs-20 h2 {
margin: 0 0 18px;
font-size: clamp(38px, 6vw, 68px);
font-weight: 800;
letter-spacing: -0.025em;
line-height: 1.05;
}
.hs-20__shine {
display: inline-block;
background: linear-gradient(90deg, #f5b148, #d63a5e, #7e2d8a, #f5b148);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: hs-20-sweep 4s linear infinite;
}
@keyframes hs-20-sweep {
to {
background-position: 200% 0;
}
}
.hs-20 p {
margin: 0 auto 26px;
font-size: 17px;
line-height: 1.55;
color: #b8a890;
max-width: 460px;
}
.hs-20__cta {
display: inline-block;
padding: 13px 26px;
background: linear-gradient(90deg, #f5b148, #d63a5e);
color: #1a0d20;
border-radius: 999px;
text-decoration: none;
font-weight: 700;
font-size: 14.5px;
box-shadow: 0 12px 30px rgba(214,58,94,0.35);
transition: transform 0.15s;
}
.hs-20__cta:hover {
transform: translateY(-1px);
}
@media (prefers-reduced-motion: reduce) {
.hs-20__shine {
animation: none;
background-position: 0 0;
}
.hs-20__cta {
transition: none;
}
}Here's a working CSS Hero Section 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: Gradient Text Spotlight
Source: https://codefronts.com/layouts/css-hero-sections/gradient-text-spotlight/
Oversized headline with an animated marigold → ruby → grape gradient sweeping across the letters. The Linear / Apple wordmark shimmer treatment.
## HTML
```html
<section class="hs-20" aria-label="Hero">
<div class="hs-20__inner">
<span class="hs-20__eye">v3 launching tuesday</span>
<h2>Made for the way <span class="hs-20__shine">creative people</span> actually work.</h2>
<p>One canvas. Every layer. Zero exporting between apps to nudge a kerning pair.</p>
<a class="hs-20__cta" href="#waitlist">Join the waitlist →</a>
</div>
</section>
```
## CSS
```css
.hs-20 {
display: grid;
place-items: center;
width: 100%;
min-height: 100vh;
padding: clamp(28px, 5vw, 64px) clamp(20px, 5vw, 56px);
background: radial-gradient(60% 60% at 50% 0%, rgba(120,30,90,0.18), transparent 70%), #1a0d20;
font-family: 'Inter', system-ui, sans-serif;
color: #f4e8d0;
box-sizing: border-box;
}
.hs-20__inner {
max-width: 720px;
text-align: center;
}
.hs-20__eye {
display: inline-block;
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
letter-spacing: 0.16em;
color: #f5b148;
padding: 4px 10px;
border: 1px solid rgba(245,177,72,0.4);
border-radius: 999px;
margin-bottom: 22px;
}
.hs-20 h2 {
margin: 0 0 18px;
font-size: clamp(38px, 6vw, 68px);
font-weight: 800;
letter-spacing: -0.025em;
line-height: 1.05;
}
.hs-20__shine {
display: inline-block;
background: linear-gradient(90deg, #f5b148, #d63a5e, #7e2d8a, #f5b148);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: hs-20-sweep 4s linear infinite;
}
@keyframes hs-20-sweep {
to {
background-position: 200% 0;
}
}
.hs-20 p {
margin: 0 auto 26px;
font-size: 17px;
line-height: 1.55;
color: #b8a890;
max-width: 460px;
}
.hs-20__cta {
display: inline-block;
padding: 13px 26px;
background: linear-gradient(90deg, #f5b148, #d63a5e);
color: #1a0d20;
border-radius: 999px;
text-decoration: none;
font-weight: 700;
font-size: 14.5px;
box-shadow: 0 12px 30px rgba(214,58,94,0.35);
transition: transform 0.15s;
}
.hs-20__cta:hover {
transform: translateY(-1px);
}
@media (prefers-reduced-motion: reduce) {
.hs-20__shine {
animation: none;
background-position: 0 0;
}
.hs-20__cta {
transition: none;
}
}
```Here's a working CSS Hero Section 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: Gradient Text Spotlight
Source: https://codefronts.com/layouts/css-hero-sections/gradient-text-spotlight/
Oversized headline with an animated marigold → ruby → grape gradient sweeping across the letters. The Linear / Apple wordmark shimmer treatment.
## HTML
```html
<section class="hs-20" aria-label="Hero">
<div class="hs-20__inner">
<span class="hs-20__eye">v3 launching tuesday</span>
<h2>Made for the way <span class="hs-20__shine">creative people</span> actually work.</h2>
<p>One canvas. Every layer. Zero exporting between apps to nudge a kerning pair.</p>
<a class="hs-20__cta" href="#waitlist">Join the waitlist →</a>
</div>
</section>
```
## CSS
```css
.hs-20 {
display: grid;
place-items: center;
width: 100%;
min-height: 100vh;
padding: clamp(28px, 5vw, 64px) clamp(20px, 5vw, 56px);
background: radial-gradient(60% 60% at 50% 0%, rgba(120,30,90,0.18), transparent 70%), #1a0d20;
font-family: 'Inter', system-ui, sans-serif;
color: #f4e8d0;
box-sizing: border-box;
}
.hs-20__inner {
max-width: 720px;
text-align: center;
}
.hs-20__eye {
display: inline-block;
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
letter-spacing: 0.16em;
color: #f5b148;
padding: 4px 10px;
border: 1px solid rgba(245,177,72,0.4);
border-radius: 999px;
margin-bottom: 22px;
}
.hs-20 h2 {
margin: 0 0 18px;
font-size: clamp(38px, 6vw, 68px);
font-weight: 800;
letter-spacing: -0.025em;
line-height: 1.05;
}
.hs-20__shine {
display: inline-block;
background: linear-gradient(90deg, #f5b148, #d63a5e, #7e2d8a, #f5b148);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: hs-20-sweep 4s linear infinite;
}
@keyframes hs-20-sweep {
to {
background-position: 200% 0;
}
}
.hs-20 p {
margin: 0 auto 26px;
font-size: 17px;
line-height: 1.55;
color: #b8a890;
max-width: 460px;
}
.hs-20__cta {
display: inline-block;
padding: 13px 26px;
background: linear-gradient(90deg, #f5b148, #d63a5e);
color: #1a0d20;
border-radius: 999px;
text-decoration: none;
font-weight: 700;
font-size: 14.5px;
box-shadow: 0 12px 30px rgba(214,58,94,0.35);
transition: transform 0.15s;
}
.hs-20__cta:hover {
transform: translateY(-1px);
}
@media (prefers-reduced-motion: reduce) {
.hs-20__shine {
animation: none;
background-position: 0 0;
}
.hs-20__cta {
transition: none;
}
}
```How this works
This gradient text hero animates a marigold → ruby → grape gradient sweep across the emphasis words creative people. The trick is on .hs-20__shine: a linear-gradient background: linear-gradient(90deg, #f5b148, #d63a5e, #7e2d8a, #f5b148) with background-size: 200% 100%, then -webkit-background-clip: text and color: transparent to mask the gradient to the letter shapes. The hs-20-sweep keyframe animates background-position from 0 to 200% over 4 seconds, linear, infinite — a continuous shimmer without any easing bounce. The gradient repeats its start color at the end (marigold appears at both 0% and 100%) so the loop point is seamless.
The section itself is display: grid; place-items: center with min-height: 100vh — the same responsive hero-section pattern used across the family — and paints a plum background (#1a0d20) with a subtle burgundy radial-gradient wash (rgba(120,30,90,0.18)) pinned to the top center. Type is Inter at font-weight: 800, letter-spacing: -0.025em, line-height: 1.05 — the SaaS-modern headline setting. The eyebrow chip uses marigold #f5b148 text inside a translucent border for the launch-teaser register.
Why it converts: gradient text signals 'cutting edge' — this is the 2023-2026 visual language of AI tools, ML platforms, and creative SaaS (Linear, Vercel, Runway, Midjourney all ship variations of this treatment). Visitors read the gradient sweep as a trust marker for AI-adjacent products the same way skeuomorphic gradients signaled 'app' in 2010. The gradient CTA below the headline (marigold → ruby) mirrors the shine treatment so the eye connects headline emphasis to conversion path in one glance.
Make it yours
- Recolor the gradient: marigold
#f5b148, ruby#d63a5e, grape#7e2d8ais the warm-to-cool sweep. For AI/ML try#00d4ff→#7e5cff→#ff3d9a. Keep 3-4 stops with the first color repeated at the end — 2-stop gradients look flat, 5+ stops look like a rainbow logo from 2007. - Swap Inter for the headline:
'Space Grotesk'for tech-forward,'General Sans'for SaaS-modern,'Instrument Serif'for editorial gradient hero (rare but stunning). Thebackground-clip: textworks on any font, but decorative/script fonts break the sweep visually because the letter shapes are too thin. - Change the CTA shape: the pill (
border-radius: 999px) with matching marigold → ruby gradient is the AI-SaaS default. For flat/brutalist swap toborder-radius: 0and drop the box-shadow. The0 12px 30px rgba(214,58,94,0.35)shadow color must match the CTA gradient end-color or the button looks unmoored. - For light mode: invert to
#faf6eecream background, dark plum#2a1830body text, keep the marigold → ruby → grape gradient on.hs-20__shine(the gradient shows against cream, though contrast per WCAG 1.4.11 needs verification). The radial-gradient wash drops opacity to 0.06. - For Tailwind:
bg-gradient-to-r from-[#f5b148] via-[#d63a5e] to-[#7e2d8a] bg-clip-text text-transparenton the shine span, plus a custom keyframe intailwind.configfor the sweep animation. In Next.js, wrap.hs-20__shineas a<GradientText>component so you can reuse it across headline, CTA, and section labels.
Gotchas — read before shipping
- The
-webkit-background-clip: textprefix is still required for full Chromium coverage — the unprefixedbackground-clip: textships in all evergreen browsers but omitting the prefix breaks Chrome 100 and earlier (~1% of your traffic). Ship both properties as the demo does; do NOT trust autoprefixer to add it because most configs no longer target that far back. - Animating
background-positionon a text-clipped gradient is one of the few animations that runs on the paint thread, NOT the compositor. It cannot be promoted withwill-change: transformbecause the property is not transform. INP is safe (~50ms) but on very long headlines (30+ characters) the paint cost per frame can push mid-tier Android to 200ms+ — keep the shine span to 2-3 words max. - Contrast: the gradient text averages roughly 6:1 against
#1a0d20at the marigold end, ~4.5:1 at the ruby end, and ~3:1 at the grape end. The grape stop FAILS WCAG AA for text under 24px. Because the gradient is animated the exact contrast at any moment varies — you cannot pass an audit tool. Either keep the shine text at 38px+ (the demo does) or narrow the gradient stops to omit the grape. - The
prefers-reduced-motionguard setsanimation: none; background-position: 0 0— this stops the sweep but preserves the gradient as a static fill, which is the correct WCAG 2.3.3 behavior. Do NOT fall back to a solid color; the gradient is the whole product signal, and users with vestibular sensitivity get a stationary version of the same brand cue. - Framework quirk:
background-clip: textwithcolor: transparentis captured correctly by Playwright and Puppeteer screenshots, but Safari's PDF renderer sometimes rasterizes it as solid black. If your users export the page to PDF (rare but real for AI-tool marketing pages), test the export — you may need to add a@media printfallback that sets a solid color. - The CTA uses
transition: transform 0.15swith atranslateY(-1px)hover — compositor-thread only, INP-safe. But thebox-shadow: 0 12px 30pxdoes NOT transition, so the shadow stays put while the button lifts. This is intentional (a moving shadow reads as gimmicky) — do not 'fix' it by adding shadow to the transition list.