31 CSS Hero Sections03 / 31
Gradient Mesh
Tropical mesh gradient — overlapping radial blobs in mango, papaya, and dragon fruit on a warm coral base. The Stripe / Linear gradient hero, but turned up to a sunset.
Published
The code
<section class="hs-03" aria-label="Hero">
<div class="hs-03__blobs" aria-hidden="true">
<span></span><span></span><span></span><span></span>
</div>
<div class="hs-03__inner">
<span class="hs-03__eye">launch · summer collection</span>
<h2>Make your weekends <em>feel like vacation.</em></h2>
<p>
The mood-board planner that turns scattered Pinterest tabs into the trip you actually take.
</p>
<a class="hs-03__cta" href="#start">Plan a trip →</a>
</div>
</section><section class="hs-03" aria-label="Hero">
<div class="hs-03__blobs" aria-hidden="true">
<span></span><span></span><span></span><span></span>
</div>
<div class="hs-03__inner">
<span class="hs-03__eye">launch · summer collection</span>
<h2>Make your weekends <em>feel like vacation.</em></h2>
<p>
The mood-board planner that turns scattered Pinterest tabs into the trip you actually take.
</p>
<a class="hs-03__cta" href="#start">Plan a trip →</a>
</div>
</section>.hs-03 {
position: relative;
overflow: hidden;
display: grid;
place-items: center;
width: 100%;
min-height: 100vh;
padding: clamp(32px, 6vw, 80px) clamp(20px, 5vw, 56px);
background: #ff5e62;
font-family: 'Inter', system-ui, sans-serif;
color: #fff;
box-sizing: border-box;
contain: layout paint;
}
.hs-03__blobs {
position: absolute;
inset: 0;
}
.hs-03__blobs span {
position: absolute;
border-radius: 50%;
filter: blur(60px);
animation: hs-03-drift 16s ease-in-out infinite alternate;
}
.hs-03__blobs span:nth-child(1) {
top: -10%;
left: 10%;
width: 460px;
height: 460px;
background: radial-gradient(circle, #ffd23f 0%, transparent 70%);
}
.hs-03__blobs span:nth-child(2) {
top: 20%;
right: 0;
width: 420px;
height: 420px;
background: radial-gradient(circle, #ee4266 0%, transparent 70%);
animation-delay: -4s;
}
.hs-03__blobs span:nth-child(3) {
bottom: 0;
left: 30%;
width: 460px;
height: 460px;
background: radial-gradient(circle, #ff7e5f 0%, transparent 70%);
animation-delay: -8s;
}
.hs-03__blobs span:nth-child(4) {
top: 30%;
left: -8%;
width: 360px;
height: 360px;
background: radial-gradient(circle, #ffa552 0%, transparent 70%);
animation-delay: -12s;
}
@keyframes hs-03-drift {
0% {
transform: translate(0,0) scale(1);
}
50% {
transform: translate(40px,-30px) scale(1.08);
}
100% {
transform: translate(-40px,40px) scale(0.96);
}
}
.hs-03__inner {
position: relative;
z-index: 1;
max-width: 640px;
text-align: center;
}
.hs-03__eye {
display: inline-block;
padding: 5px 14px;
background: rgba(255,255,255,0.18);
border: 1px solid rgba(255,255,255,0.4);
border-radius: 999px;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.14em;
text-transform: uppercase;
margin-bottom: 22px;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
.hs-03 h2 {
margin: 0 0 18px;
font-size: clamp(34px, 6vw, 60px);
font-weight: 900;
letter-spacing: -0.025em;
line-height: 1.02;
text-shadow: 0 2px 24px rgba(238,66,102,0.25);
}
.hs-03 h2 em {
font-style: italic;
font-weight: 800;
color: #fff5d2;
}
.hs-03 p {
margin: 0 auto 28px;
font-size: 17px;
line-height: 1.55;
max-width: 480px;
opacity: 0.95;
}
.hs-03__cta {
display: inline-block;
padding: 14px 26px;
background: #fff;
color: #ee4266;
border-radius: 999px;
text-decoration: none;
font-weight: 700;
font-size: 15px;
box-shadow: 0 12px 30px rgba(238,66,102,0.35);
transition: transform 0.18s;
}
.hs-03__cta:hover {
transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
.hs-03__blobs span {
animation: none;
}
.hs-03__cta {
transition: none;
}
}.hs-03 {
position: relative;
overflow: hidden;
display: grid;
place-items: center;
width: 100%;
min-height: 100vh;
padding: clamp(32px, 6vw, 80px) clamp(20px, 5vw, 56px);
background: #ff5e62;
font-family: 'Inter', system-ui, sans-serif;
color: #fff;
box-sizing: border-box;
contain: layout paint;
}
.hs-03__blobs {
position: absolute;
inset: 0;
}
.hs-03__blobs span {
position: absolute;
border-radius: 50%;
filter: blur(60px);
animation: hs-03-drift 16s ease-in-out infinite alternate;
}
.hs-03__blobs span:nth-child(1) {
top: -10%;
left: 10%;
width: 460px;
height: 460px;
background: radial-gradient(circle, #ffd23f 0%, transparent 70%);
}
.hs-03__blobs span:nth-child(2) {
top: 20%;
right: 0;
width: 420px;
height: 420px;
background: radial-gradient(circle, #ee4266 0%, transparent 70%);
animation-delay: -4s;
}
.hs-03__blobs span:nth-child(3) {
bottom: 0;
left: 30%;
width: 460px;
height: 460px;
background: radial-gradient(circle, #ff7e5f 0%, transparent 70%);
animation-delay: -8s;
}
.hs-03__blobs span:nth-child(4) {
top: 30%;
left: -8%;
width: 360px;
height: 360px;
background: radial-gradient(circle, #ffa552 0%, transparent 70%);
animation-delay: -12s;
}
@keyframes hs-03-drift {
0% {
transform: translate(0,0) scale(1);
}
50% {
transform: translate(40px,-30px) scale(1.08);
}
100% {
transform: translate(-40px,40px) scale(0.96);
}
}
.hs-03__inner {
position: relative;
z-index: 1;
max-width: 640px;
text-align: center;
}
.hs-03__eye {
display: inline-block;
padding: 5px 14px;
background: rgba(255,255,255,0.18);
border: 1px solid rgba(255,255,255,0.4);
border-radius: 999px;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.14em;
text-transform: uppercase;
margin-bottom: 22px;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
.hs-03 h2 {
margin: 0 0 18px;
font-size: clamp(34px, 6vw, 60px);
font-weight: 900;
letter-spacing: -0.025em;
line-height: 1.02;
text-shadow: 0 2px 24px rgba(238,66,102,0.25);
}
.hs-03 h2 em {
font-style: italic;
font-weight: 800;
color: #fff5d2;
}
.hs-03 p {
margin: 0 auto 28px;
font-size: 17px;
line-height: 1.55;
max-width: 480px;
opacity: 0.95;
}
.hs-03__cta {
display: inline-block;
padding: 14px 26px;
background: #fff;
color: #ee4266;
border-radius: 999px;
text-decoration: none;
font-weight: 700;
font-size: 15px;
box-shadow: 0 12px 30px rgba(238,66,102,0.35);
transition: transform 0.18s;
}
.hs-03__cta:hover {
transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
.hs-03__blobs span {
animation: none;
}
.hs-03__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 Mesh
Source: https://codefronts.com/layouts/css-hero-sections/gradient-mesh/
Tropical mesh gradient — overlapping radial blobs in mango, papaya, and dragon fruit on a warm coral base. The Stripe / Linear gradient hero, but turned up to a sunset.
## HTML
```html
<section class="hs-03" aria-label="Hero">
<div class="hs-03__blobs" aria-hidden="true">
<span></span><span></span><span></span><span></span>
</div>
<div class="hs-03__inner">
<span class="hs-03__eye">launch · summer collection</span>
<h2>Make your weekends <em>feel like vacation.</em></h2>
<p>
The mood-board planner that turns scattered Pinterest tabs into the trip you actually take.
</p>
<a class="hs-03__cta" href="#start">Plan a trip →</a>
</div>
</section>
```
## CSS
```css
.hs-03 {
position: relative;
overflow: hidden;
display: grid;
place-items: center;
width: 100%;
min-height: 100vh;
padding: clamp(32px, 6vw, 80px) clamp(20px, 5vw, 56px);
background: #ff5e62;
font-family: 'Inter', system-ui, sans-serif;
color: #fff;
box-sizing: border-box;
contain: layout paint;
}
.hs-03__blobs {
position: absolute;
inset: 0;
}
.hs-03__blobs span {
position: absolute;
border-radius: 50%;
filter: blur(60px);
animation: hs-03-drift 16s ease-in-out infinite alternate;
}
.hs-03__blobs span:nth-child(1) {
top: -10%;
left: 10%;
width: 460px;
height: 460px;
background: radial-gradient(circle, #ffd23f 0%, transparent 70%);
}
.hs-03__blobs span:nth-child(2) {
top: 20%;
right: 0;
width: 420px;
height: 420px;
background: radial-gradient(circle, #ee4266 0%, transparent 70%);
animation-delay: -4s;
}
.hs-03__blobs span:nth-child(3) {
bottom: 0;
left: 30%;
width: 460px;
height: 460px;
background: radial-gradient(circle, #ff7e5f 0%, transparent 70%);
animation-delay: -8s;
}
.hs-03__blobs span:nth-child(4) {
top: 30%;
left: -8%;
width: 360px;
height: 360px;
background: radial-gradient(circle, #ffa552 0%, transparent 70%);
animation-delay: -12s;
}
@keyframes hs-03-drift {
0% {
transform: translate(0,0) scale(1);
}
50% {
transform: translate(40px,-30px) scale(1.08);
}
100% {
transform: translate(-40px,40px) scale(0.96);
}
}
.hs-03__inner {
position: relative;
z-index: 1;
max-width: 640px;
text-align: center;
}
.hs-03__eye {
display: inline-block;
padding: 5px 14px;
background: rgba(255,255,255,0.18);
border: 1px solid rgba(255,255,255,0.4);
border-radius: 999px;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.14em;
text-transform: uppercase;
margin-bottom: 22px;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
.hs-03 h2 {
margin: 0 0 18px;
font-size: clamp(34px, 6vw, 60px);
font-weight: 900;
letter-spacing: -0.025em;
line-height: 1.02;
text-shadow: 0 2px 24px rgba(238,66,102,0.25);
}
.hs-03 h2 em {
font-style: italic;
font-weight: 800;
color: #fff5d2;
}
.hs-03 p {
margin: 0 auto 28px;
font-size: 17px;
line-height: 1.55;
max-width: 480px;
opacity: 0.95;
}
.hs-03__cta {
display: inline-block;
padding: 14px 26px;
background: #fff;
color: #ee4266;
border-radius: 999px;
text-decoration: none;
font-weight: 700;
font-size: 15px;
box-shadow: 0 12px 30px rgba(238,66,102,0.35);
transition: transform 0.18s;
}
.hs-03__cta:hover {
transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
.hs-03__blobs span {
animation: none;
}
.hs-03__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 Mesh
Source: https://codefronts.com/layouts/css-hero-sections/gradient-mesh/
Tropical mesh gradient — overlapping radial blobs in mango, papaya, and dragon fruit on a warm coral base. The Stripe / Linear gradient hero, but turned up to a sunset.
## HTML
```html
<section class="hs-03" aria-label="Hero">
<div class="hs-03__blobs" aria-hidden="true">
<span></span><span></span><span></span><span></span>
</div>
<div class="hs-03__inner">
<span class="hs-03__eye">launch · summer collection</span>
<h2>Make your weekends <em>feel like vacation.</em></h2>
<p>
The mood-board planner that turns scattered Pinterest tabs into the trip you actually take.
</p>
<a class="hs-03__cta" href="#start">Plan a trip →</a>
</div>
</section>
```
## CSS
```css
.hs-03 {
position: relative;
overflow: hidden;
display: grid;
place-items: center;
width: 100%;
min-height: 100vh;
padding: clamp(32px, 6vw, 80px) clamp(20px, 5vw, 56px);
background: #ff5e62;
font-family: 'Inter', system-ui, sans-serif;
color: #fff;
box-sizing: border-box;
contain: layout paint;
}
.hs-03__blobs {
position: absolute;
inset: 0;
}
.hs-03__blobs span {
position: absolute;
border-radius: 50%;
filter: blur(60px);
animation: hs-03-drift 16s ease-in-out infinite alternate;
}
.hs-03__blobs span:nth-child(1) {
top: -10%;
left: 10%;
width: 460px;
height: 460px;
background: radial-gradient(circle, #ffd23f 0%, transparent 70%);
}
.hs-03__blobs span:nth-child(2) {
top: 20%;
right: 0;
width: 420px;
height: 420px;
background: radial-gradient(circle, #ee4266 0%, transparent 70%);
animation-delay: -4s;
}
.hs-03__blobs span:nth-child(3) {
bottom: 0;
left: 30%;
width: 460px;
height: 460px;
background: radial-gradient(circle, #ff7e5f 0%, transparent 70%);
animation-delay: -8s;
}
.hs-03__blobs span:nth-child(4) {
top: 30%;
left: -8%;
width: 360px;
height: 360px;
background: radial-gradient(circle, #ffa552 0%, transparent 70%);
animation-delay: -12s;
}
@keyframes hs-03-drift {
0% {
transform: translate(0,0) scale(1);
}
50% {
transform: translate(40px,-30px) scale(1.08);
}
100% {
transform: translate(-40px,40px) scale(0.96);
}
}
.hs-03__inner {
position: relative;
z-index: 1;
max-width: 640px;
text-align: center;
}
.hs-03__eye {
display: inline-block;
padding: 5px 14px;
background: rgba(255,255,255,0.18);
border: 1px solid rgba(255,255,255,0.4);
border-radius: 999px;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.14em;
text-transform: uppercase;
margin-bottom: 22px;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
.hs-03 h2 {
margin: 0 0 18px;
font-size: clamp(34px, 6vw, 60px);
font-weight: 900;
letter-spacing: -0.025em;
line-height: 1.02;
text-shadow: 0 2px 24px rgba(238,66,102,0.25);
}
.hs-03 h2 em {
font-style: italic;
font-weight: 800;
color: #fff5d2;
}
.hs-03 p {
margin: 0 auto 28px;
font-size: 17px;
line-height: 1.55;
max-width: 480px;
opacity: 0.95;
}
.hs-03__cta {
display: inline-block;
padding: 14px 26px;
background: #fff;
color: #ee4266;
border-radius: 999px;
text-decoration: none;
font-weight: 700;
font-size: 15px;
box-shadow: 0 12px 30px rgba(238,66,102,0.35);
transition: transform 0.18s;
}
.hs-03__cta:hover {
transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
.hs-03__blobs span {
animation: none;
}
.hs-03__cta {
transition: none;
}
}
```How this works
The hero uses position: relative; overflow: hidden as a stacking-context boundary with four absolutely-positioned <span> blobs painted underneath the copy layer. Each blob is a radial-gradient circle with filter: blur(60px) — the blur is what turns four solid discs into a soft mesh. The critical performance detail is contain: layout paint on the section: this tells the browser the blob repaints can't affect anything outside the hero, so scroll and hover events elsewhere on the page never trigger a full-document repaint. Core Web Vitals stay green even with four continuously-animating blobs.
The palette is turned-up-to-sunset — coral base (#ff5e62), yellow blob (#ffd23f), magenta blob (#ee4266), warm orange blobs (#ff7e5f, #ffa552) — the Stripe / Linear / Vercel gradient mesh hero language, but shifted from purple-blue into fintech-adjacent warm tones. Inter at font-weight: 900 with letter-spacing: -0.025em and a text-shadow: 0 2px 24px rgba(238,66,102,0.25) gives the headline a soft magenta glow that reads as "backlit" without looking blurry. The pill-shaped white CTA with box-shadow: 0 12px 30px rgba(238,66,102,0.35) floats above the mesh — the shadow color matches the magenta blob, so the CTA feels like it's casting real light onto real fabric.
Why it converts: gradient mesh heroes signal "modern, AI-adjacent, well-funded" — the visual language of Stripe, Linear, Vercel, OpenAI, and every YC startup that raised a Series A in the last two years. Visitors who've seen this treatment on those brands read a new site with the same treatment as legitimate before they read a word of copy. The pill CTA in pure white against the mesh is the highest-contrast element on the page — the eye lands on it involuntarily. That involuntary landing is the entire conversion funnel condensed into one visual hierarchy trick.
Make it yours
- Recolor the mesh by editing the four blob radial-gradient centers:
#ffd23f,#ee4266,#ff7e5f,#ffa552. For a fintech-cool mesh, shift to#7c5cff,#4dabf7,#5eead4,#c084fc. Keep the base#ff5e62deep enough that the CTA shadow color has something to sit against. - Swap the type: Inter at 900 is the SaaS hero section default. For a startup hero with more character use
'Instrument Serif'atfont-weight: 400with italic. For AI/dev-tools shift to'Geist'or'Space Grotesk'atfont-weight: 700. Keep thetext-shadowglow either way — it's the mesh cue. - Change the CTA shape: pill (
border-radius: 999px) is the mesh-hero default. For a more editorial gradient mesh hero tryborder-radius: 8pxwith a chunkierbox-shadow: 0 20px 40px rgba(238,66,102,0.4). For brutalist gradient useborder-radius: 0and drop the shadow entirely. - For dark mode: the mesh already reads dark-friendly. Shift the base to
#1a0f2e, keep the blob colors but drop opacity to 0.7 viargba(), and change the CTA tobackground: rgba(255,255,255,0.12); backdrop-filter: blur(12px); color: #fff; border: 1px solid rgba(255,255,255,0.3)— glass on dark mesh is the aurora/Vercel dark mode pattern. - For Tailwind:
relative overflow-hidden grid place-items-center bg-[#ff5e62] [contain:layout_paint]on section,font-black text-6xl tracking-tighter leading-[1.02] [text-shadow:0_2px_24px_rgba(238,66,102,0.25)]on h2,bg-white text-[#ee4266] rounded-full shadow-[0_12px_30px_rgba(238,66,102,0.35)] hover:-translate-y-0.5on CTA.
Gotchas — read before shipping
- The four
filter: blur(60px)blobs are the biggest paint cost in the file. On mid-tier Android (Snapdragon 6-gen), continuous animation of blurred elements can spike INP past 200ms if anything else on the page triggers layout. Thecontain: layout paintis load-bearing — never remove it, and never nest the mesh inside a transformed ancestor which breaks containment. - The
backdrop-filter: blur(8px)on the eyebrow pill fails silently on Firefox untillayout.css.backdrop-filter.enabledis set (default on since v103) — but older evergreen users still see a plain translucent pill. Ship a@supports not (backdrop-filter: blur(8px))fallback with a solidrgba(255,255,255,0.4)so the pill never disappears. - The CTA text (
#ee4266magenta) on white background hits contrast ~4.8:1 — passes WCAG AA for large text but not AAA. If you shrink the CTA font below 15px or drop the weight below 700, contrast fails. Verify with an automated axe scan before shipping — landing-page hero CTA contrast is the single most-flagged a11y issue on scans. - The
animation: hs-03-drift 16s ease-in-out infinite alternatekeeps blobs in constant motion —prefers-reduced-motion: reducedisables it. This is required for WCAG 2.3.3 conformance; users with vestibular disorders find continuous drift nauseating even at low amplitudes. Never comment out the media query "just to see the effect" and forget to restore it. - In React, if you conditionally render the mesh (
{showMesh && <GradientMeshHero />}) the initial mount triggers a full paint of four 460px blurred spans — a ~40ms first-paint hit on mid-tier mobile. Preload the component withReact.lazy+Suspenseand let it hydrate off the critical path, or the largest-contentful-paint delay counts against LCP. - The blob animation uses
transform: translate() scale()which is compositor-thread safe. Do NOT switch to animatingtop,left,width, orheightfor "cleaner" positioning — those trigger layout every frame and destroy INP scores. If you need to reposition blobs responsively, use CSS custom properties updated via@media, not JS.