20 CSS Gradient Text Designs 13 / 20
CSS Hover Reveal Gradient Text Effect
Each line of text sits in a muted grey state until hovered, triggering a smooth transition that unveils a distinct gradient per line using -webkit-text-fill-color toggling.
The code
<div class="gt-13"> <span class="gt-13__label">Hover to reveal gradient</span> <span class="gt-13__hint">↓ mouse over each line ↓</span> <div class="gt-13__line gt-13__line--a">CREATIVITY</div> <div class="gt-13__line gt-13__line--b">EXPLORATION</div> <div class="gt-13__line gt-13__line--c">INNOVATION</div> <div class="gt-13__line gt-13__line--d">EXPRESSION</div> <div class="gt-13__line gt-13__line--e">INSPIRATION</div> <div class="gt-13__line gt-13__line--f">MOMENTUM</div> </div>
<div class="gt-13">
<span class="gt-13__label">Hover to reveal gradient</span>
<span class="gt-13__hint">↓ mouse over each line ↓</span>
<div class="gt-13__line gt-13__line--a">CREATIVITY</div>
<div class="gt-13__line gt-13__line--b">EXPLORATION</div>
<div class="gt-13__line gt-13__line--c">INNOVATION</div>
<div class="gt-13__line gt-13__line--d">EXPRESSION</div>
<div class="gt-13__line gt-13__line--e">INSPIRATION</div>
<div class="gt-13__line gt-13__line--f">MOMENTUM</div>
</div>.gt-13, .gt-13 *, .gt-13 *::before, .gt-13 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.gt-13 {
--bg: #0f0f14;
--plain: #888;
font-family: 'Plus Jakarta Sans', sans-serif;
background: var(--bg);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1.5rem;
padding: 3rem 2rem;
cursor: default;
}
.gt-13__label {
font-size: .7rem;
letter-spacing: .2em;
text-transform: uppercase;
color: #333;
margin-bottom: 1rem;
}
.gt-13__hint {
font-size: .75rem;
letter-spacing: .1em;
color: #444;
margin-bottom: 1rem;
}
/* Each line transitions from plain → gradient on hover */
.gt-13__line {
font-size: clamp(2.5rem, 9vw, 6rem);
font-weight: 800;
line-height: 1.05;
letter-spacing: -.01em;
position: relative;
display: inline-block;
cursor: pointer;
/* Plain state */
color: var(--plain);
transition: color .4s ease;
/* Gradient hidden under colour */
background: linear-gradient(90deg, #f093fb, #f5576c, #fda085);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
}
.gt-13__line:hover {
-webkit-text-fill-color: transparent;
color: transparent;
background-position: 100% center;
transition: background-position .6s ease, color .1s;
animation: gt-13-flow .6s ease forwards;
}
.gt-13__line--b {
background-image: linear-gradient(90deg, #43e97b, #38f9d7, #4facfe);
}
.gt-13__line--c {
background-image: linear-gradient(90deg, #fa709a, #fee140, #a18cd1);
}
.gt-13__line--d {
background-image: linear-gradient(90deg, #30cfd0, #330867, #e0c3fc);
}
.gt-13__line--e {
background-image: linear-gradient(90deg, #ff9a9e, #fecfef, #ffecd2);
}
.gt-13__line--f {
background-image: linear-gradient(90deg, #a1c4fd, #c2e9fb, #d4fc79);
}
@keyframes gt-13-flow {
0% { background-position: 0% center; }
100% { background-position: 100% center; }
}
@media (prefers-reduced-motion: reduce) {
.gt-13__line:hover { animation: none; background-position: 0% center; }
} .gt-13, .gt-13 *, .gt-13 *::before, .gt-13 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.gt-13 {
--bg: #0f0f14;
--plain: #888;
font-family: 'Plus Jakarta Sans', sans-serif;
background: var(--bg);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1.5rem;
padding: 3rem 2rem;
cursor: default;
}
.gt-13__label {
font-size: .7rem;
letter-spacing: .2em;
text-transform: uppercase;
color: #333;
margin-bottom: 1rem;
}
.gt-13__hint {
font-size: .75rem;
letter-spacing: .1em;
color: #444;
margin-bottom: 1rem;
}
/* Each line transitions from plain → gradient on hover */
.gt-13__line {
font-size: clamp(2.5rem, 9vw, 6rem);
font-weight: 800;
line-height: 1.05;
letter-spacing: -.01em;
position: relative;
display: inline-block;
cursor: pointer;
/* Plain state */
color: var(--plain);
transition: color .4s ease;
/* Gradient hidden under colour */
background: linear-gradient(90deg, #f093fb, #f5576c, #fda085);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
}
.gt-13__line:hover {
-webkit-text-fill-color: transparent;
color: transparent;
background-position: 100% center;
transition: background-position .6s ease, color .1s;
animation: gt-13-flow .6s ease forwards;
}
.gt-13__line--b {
background-image: linear-gradient(90deg, #43e97b, #38f9d7, #4facfe);
}
.gt-13__line--c {
background-image: linear-gradient(90deg, #fa709a, #fee140, #a18cd1);
}
.gt-13__line--d {
background-image: linear-gradient(90deg, #30cfd0, #330867, #e0c3fc);
}
.gt-13__line--e {
background-image: linear-gradient(90deg, #ff9a9e, #fecfef, #ffecd2);
}
.gt-13__line--f {
background-image: linear-gradient(90deg, #a1c4fd, #c2e9fb, #d4fc79);
}
@keyframes gt-13-flow {
0% { background-position: 0% center; }
100% { background-position: 100% center; }
}
@media (prefers-reduced-motion: reduce) {
.gt-13__line:hover { animation: none; background-position: 0% center; }
}How this works
In the default state, -webkit-text-fill-color is set to the muted var(--plain) colour which paints over the background-clipped gradient beneath. On :hover, a CSS rule sets -webkit-text-fill-color: transparent, which unmasks the pre-painted gradient. Because the gradient is always present as the background, the reveal is instant — there is no gradient recalculation on hover, only a property toggle.
The color and -webkit-text-fill-color transition in opposite directions during hover entry and exit, which produces the smooth reveal without animating the gradient itself. Each line has its own gradient image defined via a modifier class (.gt-13__line--b, etc.) so all six gradients are parsed at load time.
Customize
- Add a
transform: skewX(-2deg)on:hoverto give the reveal a subtle italic lean that emphasises the motion. - Replace the hover trigger with
:focus-withinto make the effect keyboard-accessible — wrap each line in a button element. - Set
transition-duration: .2sfor a snappier reveal, or1s ease-in-outfor a cinematic slow unveil of each gradient.
Watch out for
- Setting both
colorand-webkit-text-fill-coloron the same element at the same time causes unexpected results in Firefox — set only-webkit-text-fill-colorfor the masking trick and keepcoloras a fallback. - Touch devices do not have a persistent hover state — the gradient reveals and immediately resets on touch. Use a
:focusrule as a touch-compatible alternative. - The background gradient is always painted even in the masked (grey) state — this wastes GPU memory if many gradient-text elements exist off-screen; use
content-visibility: autoon sections below the fold.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 4+ | 3.1+ | 49+ | 4+ |
The -webkit-text-fill-color toggling technique works in all modern browsers; the prefixed property is necessary for this specific masking trick on all platforms.