How to Create a Shimmer Text Effect with CSS
Step-by-step guide to building a shimmer text effect using CSS gradients, background-clip, and keyframe animations. Includes customization tips and live examples.
The shimmer text effect — a gradient highlight that sweeps across text — is one of those small details that can make a heading feel alive. You see it on product landing pages, pricing highlights, and hero sections. It's surprisingly simple to build with pure CSS.
Here's how it works, step by step.
The Core Technique
The shimmer effect relies on three CSS properties working together:
background: linear-gradient(...)— a gradient with a highlight bandbackground-clip: text— clips the background to the text shapeanimation— moves the gradient position across the text
Let's build it.
Step 1: Set Up the Gradient Background
Start with a linear gradient that includes a bright highlight band:
.shimmer {
background: linear-gradient(
90deg,
#334155 0%,
#334155 40%,
#e2e8f0 50%,
#334155 60%,
#334155 100%
);
background-size: 200% 100%;
}
The gradient is mostly a dark color (#334155) with a light highlight (#e2e8f0) in the center. Setting background-size: 200% 100% makes the gradient twice as wide as the element, so we can slide it across.
Step 2: Clip the Background to Text
.shimmer {
/* ...gradient from above */
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
}
background-clip: text makes the gradient only visible through the text glyphs. The -webkit- prefix is still needed for Safari. Setting color: transparent (along with -webkit-text-fill-color: transparent) ensures the text color doesn't paint over the gradient.
Step 3: Animate the Position
@keyframes shimmer-slide {
0% {
background-position: 100% center;
}
100% {
background-position: -100% center;
}
}
.shimmer {
/* ...gradient and clipping from above */
animation: shimmer-slide 3s ease-in-out infinite;
}
The animation shifts background-position from right to left, creating the illusion of a light sweeping across the text.
Complete Code
Here's the full implementation:
.shimmer {
background: linear-gradient(
90deg,
#334155 0%,
#334155 40%,
#e2e8f0 50%,
#334155 60%,
#334155 100%
);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
animation: shimmer-slide 3s ease-in-out infinite;
}
@keyframes shimmer-slide {
0% {
background-position: 100% center;
}
100% {
background-position: -100% center;
}
}
Apply the .shimmer class to any text element and you're done.
Variations
Color Shimmer
Instead of a light-on-dark highlight, use two colors:
.shimmer-color {
background: linear-gradient(
90deg,
#6366f1 0%,
#6366f1 40%,
#ec4899 50%,
#6366f1 60%,
#6366f1 100%
);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
animation: shimmer-slide 3s ease-in-out infinite;
}
This creates a pink highlight sweeping across indigo text.
Slower, Subtler Shimmer
For a more understated effect, widen the highlight band, soften the color difference, and slow the animation:
.shimmer-subtle {
background: linear-gradient(
90deg,
#64748b 0%,
#64748b 30%,
#94a3b8 50%,
#64748b 70%,
#64748b 100%
);
background-size: 250% 100%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
animation: shimmer-slide 5s ease-in-out infinite;
}
Single Sweep (No Loop)
If you want the shimmer to play once when the element enters the viewport rather than looping:
.shimmer-once {
/* ...same gradient and clipping */
animation: shimmer-slide 1.5s ease-out forwards;
background-position: 100% center;
}
Pair this with IntersectionObserver to trigger the animation on scroll.
Dark Mode
For dark backgrounds, invert the colors — use light text as the base with a brighter white as the highlight:
.shimmer-dark {
background: linear-gradient(
90deg,
#94a3b8 0%,
#94a3b8 40%,
#f8fafc 50%,
#94a3b8 60%,
#94a3b8 100%
);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
animation: shimmer-slide 3s ease-in-out infinite;
}
Performance Notes
The shimmer effect is lightweight. Animating background-position on a text element is cheap because:
- The element is typically small (a heading)
- No layout or paint is triggered — just compositing
background-clip: textis well-optimized in modern browsers
That said, avoid applying this to large blocks of body text. It's meant for headings and short phrases.
Browser Support
background-clip: text is supported in all modern browsers. The -webkit- prefix is still recommended for Safari compatibility. This technique works in Chrome, Firefox, Safari, and Edge.
Ready-Made Alternative
If you want this effect without writing the CSS yourself, Spell UI has a ShimmerText component that wraps this technique with configurable colors, speed, and animation direction. Install it via the CLI and drop it into your JSX.
But honestly, the CSS is simple enough that building it yourself is a perfectly good option. Copy the snippet above, adjust the colors to match your brand, and you're set.