20 CSS Text Gradient Effects 02 / 20
Web3 Glowing Gradient Text CSS
A cyberpunk-inspired Web3 card where a blurred duplicate element creates a neon glow bloom effect behind the gradient text.
The code
<div class="tg-02">
<div class="tg-02__card">
<div class="tg-02__eyebrow">⬡ Decentralized Protocol</div>
<h2 class="tg-02__title">Own Your<br><span class="tg-02__glow-wrap"><span class="tg-02__glow-text">Digital Future</span><span class="tg-02__glow-bloom" aria-hidden="true">Digital Future</span></span></h2>
<p class="tg-02__desc">Stake, earn, and govern—powered by transparent on-chain contracts.</p>
<div class="tg-02__pill-row">
<span class="tg-02__pill">Polygon</span>
<span class="tg-02__pill">Solana</span>
<span class="tg-02__pill">Ethereum</span>
</div>
</div>
</div> <div class="tg-02">
<div class="tg-02__card">
<div class="tg-02__eyebrow">⬡ Decentralized Protocol</div>
<h2 class="tg-02__title">Own Your<br><span class="tg-02__glow-wrap"><span class="tg-02__glow-text">Digital Future</span><span class="tg-02__glow-bloom" aria-hidden="true">Digital Future</span></span></h2>
<p class="tg-02__desc">Stake, earn, and govern—powered by transparent on-chain contracts.</p>
<div class="tg-02__pill-row">
<span class="tg-02__pill">Polygon</span>
<span class="tg-02__pill">Solana</span>
<span class="tg-02__pill">Ethereum</span>
</div>
</div>
</div>.tg-02, .tg-02 *, .tg-02 *::before, .tg-02 *::after { margin:0; padding:0; box-sizing:border-box; }
.tg-02 ::selection { background:#0ff2; color:#fff; }
.tg-02 {
--neon-a: #00f0ff;
--neon-b: #a855f7;
--neon-c: #ff2d78;
--bg: #040714;
--card-bg: rgba(255,255,255,.03);
--border: rgba(0,240,255,.12);
--text: #e2e8f0;
--muted: #7dd3fc;
font-family: system-ui, -apple-system, sans-serif;
background: var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 48px 24px;
}
.tg-02__card {
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 20px;
padding: 48px 40px;
max-width: 560px;
text-align: center;
backdrop-filter: blur(12px);
}
.tg-02__eyebrow {
font-size: .8125rem;
font-weight: 600;
letter-spacing: .1em;
color: var(--neon-a);
margin-bottom: 20px;
}
.tg-02__title {
font-size: clamp(2rem, 6vw, 3.5rem);
font-weight: 900;
line-height: 1.1;
color: var(--text);
letter-spacing: -.03em;
margin-bottom: 20px;
}
/* Glow technique: gradient text + absolute blurred copy for bloom */
.tg-02__glow-wrap {
position: relative;
display: inline-block;
}
.tg-02__glow-text {
background: linear-gradient(90deg, var(--neon-a) 0%, var(--neon-b) 55%, var(--neon-c) 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
position: relative;
z-index: 1;
}
/* Blurred duplicate creates the neon glow bloom */
.tg-02__glow-bloom {
position: absolute;
inset: 0;
background: linear-gradient(90deg, var(--neon-a) 0%, var(--neon-b) 55%, var(--neon-c) 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
filter: blur(18px);
opacity: .55;
z-index: 0;
animation: tg-02-pulse 3s ease-in-out infinite;
}
@keyframes tg-02-pulse {
0%, 100% { opacity: .4; filter: blur(18px); }
50% { opacity: .75; filter: blur(22px); }
}
.tg-02__desc {
color: var(--muted);
font-size: .9375rem;
line-height: 1.7;
margin-bottom: 28px;
}
.tg-02__pill-row { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.tg-02__pill {
font-size: .8125rem;
font-weight: 600;
padding: 5px 14px;
border-radius: 99px;
border: 1px solid rgba(0,240,255,.25);
color: var(--neon-a);
background: rgba(0,240,255,.06);
}
@media (prefers-reduced-motion: reduce) {
.tg-02__glow-bloom { animation: none; opacity: .5; }
} .tg-02, .tg-02 *, .tg-02 *::before, .tg-02 *::after { margin:0; padding:0; box-sizing:border-box; }
.tg-02 ::selection { background:#0ff2; color:#fff; }
.tg-02 {
--neon-a: #00f0ff;
--neon-b: #a855f7;
--neon-c: #ff2d78;
--bg: #040714;
--card-bg: rgba(255,255,255,.03);
--border: rgba(0,240,255,.12);
--text: #e2e8f0;
--muted: #7dd3fc;
font-family: system-ui, -apple-system, sans-serif;
background: var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 48px 24px;
}
.tg-02__card {
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 20px;
padding: 48px 40px;
max-width: 560px;
text-align: center;
backdrop-filter: blur(12px);
}
.tg-02__eyebrow {
font-size: .8125rem;
font-weight: 600;
letter-spacing: .1em;
color: var(--neon-a);
margin-bottom: 20px;
}
.tg-02__title {
font-size: clamp(2rem, 6vw, 3.5rem);
font-weight: 900;
line-height: 1.1;
color: var(--text);
letter-spacing: -.03em;
margin-bottom: 20px;
}
/* Glow technique: gradient text + absolute blurred copy for bloom */
.tg-02__glow-wrap {
position: relative;
display: inline-block;
}
.tg-02__glow-text {
background: linear-gradient(90deg, var(--neon-a) 0%, var(--neon-b) 55%, var(--neon-c) 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
position: relative;
z-index: 1;
}
/* Blurred duplicate creates the neon glow bloom */
.tg-02__glow-bloom {
position: absolute;
inset: 0;
background: linear-gradient(90deg, var(--neon-a) 0%, var(--neon-b) 55%, var(--neon-c) 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
filter: blur(18px);
opacity: .55;
z-index: 0;
animation: tg-02-pulse 3s ease-in-out infinite;
}
@keyframes tg-02-pulse {
0%, 100% { opacity: .4; filter: blur(18px); }
50% { opacity: .75; filter: blur(22px); }
}
.tg-02__desc {
color: var(--muted);
font-size: .9375rem;
line-height: 1.7;
margin-bottom: 28px;
}
.tg-02__pill-row { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.tg-02__pill {
font-size: .8125rem;
font-weight: 600;
padding: 5px 14px;
border-radius: 99px;
border: 1px solid rgba(0,240,255,.25);
color: var(--neon-a);
background: rgba(0,240,255,.06);
}
@media (prefers-reduced-motion: reduce) {
.tg-02__glow-bloom { animation: none; opacity: .5; }
}How this works
The glow bloom is created by stacking two identical inline elements inside a position: relative wrapper. The front layer is the true gradient text using background-clip: text. The .tg-02__glow-bloom element is positioned absolute inset: 0 behind it via z-index, with an identical gradient-clip applied and filter: blur(18px) spreading it into a soft halo.
The bloom element pulses via a @keyframes tg-02-pulse animation that oscillates opacity between 0.4 and 0.75 and filter blur between 18px and 22px. Because only opacity and filter are animated — both compositor-only properties — the animation runs entirely on the GPU without triggering layout or paint.
Customize
- Control bloom spread by editing
filter: blur(18px)on.tg-02__glow-bloom— higher values create a wider, softer halo; lower values tighten the glow to the letterforms. - Speed up or slow down the pulse by changing the
3sduration inanimation: tg-02-pulse 3s ease-in-out infiniteto suit the energy of the page. - Shift the gradient direction from left-to-right (
90deg) to diagonal (135deg) for a more dynamic angle that references common Web3 visual languages. - Reduce bloom opacity for subtler neon by lowering the
opacity: .55on the base state to.3and the50%keyframe peak to.55. - Add a third neon colour stop between the existing two in
linear-gradient(90deg, var(--neon-a) 0%, NEW 45%, var(--neon-b) 55%, var(--neon-c) 100%)for a richer spectrum.
Watch out for
- The glow bloom technique doubles the DOM node count — keep bloom elements limited to single headline words rather than long paragraphs, where the blur radius would create excessive paint area.
filter: blur()on an absolutely positioned element can create a compositing layer per element; limit concurrent blooms to 2–3 on the same screen to avoid GPU memory pressure on mobile devices.- Safari <14 does not support
filteron inline elements — test on macOS Safari 13 by checking whether the bloom halo renders or disappears silently.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 69+ | 12.1+ | 83+ | 69+ |
filter: drop-shadow on background-clip:text elements may render without the shadow shape in Firefox <83 — test in ESR builds.