Tutorial · Beginner · 6 min
Build a frosted-glass card with CSS
The frosted-glass look — a translucent panel that blurs whatever sits behind it — turns a flat card into something that feels layered and physical. It takes four CSS properties. Here's each one, and why it matters.
1. You need something behind the glass
Glass only reads as glass when there's color and detail behind it to blur. Start with a vivid backdrop, then place a card on top. Without this step the effect is invisible, which is the single most common reason glassmorphism "doesn't work."
.scene {
min-height: 320px;
display: grid;
place-items: center;
background: linear-gradient(120deg, #4F46E5, #6366F1 60%, #0EA5E9);
} 2. Make the panel translucent
The card's own background has to be semi-transparent so the blur shows through. Keep the alpha low —
somewhere around 0.15 to 0.3. Too opaque and you've just made a solid card;
too clear and the text loses contrast.
.glass {
background: rgba(255, 255, 255, 0.18);
padding: 28px 32px;
border-radius: 20px;
color: #fff;
} 3. Add the blur
This is the property doing the real work. backdrop-filter blurs the pixels behind
the element, not the element itself. A touch of saturate() revives the colors the blur would
otherwise mute. Always include the -webkit- prefix for Safari.
.glass {
backdrop-filter: blur(12px) saturate(160%);
-webkit-backdrop-filter: blur(12px) saturate(160%);
} 4. Catch the edge with a light border
Real glass has a bright rim where light hits its edge. A single hairline border in low-opacity white sells the illusion. Finish with a soft shadow so the card lifts off the backdrop.
.glass {
border: 1px solid rgba(255, 255, 255, 0.35);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
} Putting it together
That's the whole recipe: a colorful backdrop, a translucent fill, backdrop-filter, and a
light border. Adjust the blur and alpha until the text stays readable over the busiest part of your
background — that's the real test.
A note on performance and contrast
backdrop-filter is GPU-accelerated, but it still costs more than a flat fill, so reserve it
for a few hero panels rather than every card in a list. And because the backdrop changes the contrast
behind your text, check readability against your darkest and lightest background regions, not just the
average — accessibility lives in the worst case.
Handling older browsers
Every current browser supports backdrop-filter, but you may still want a graceful fallback
for the rare old one. The clean way is a feature query: set a more opaque background by default, then
lighten it only where the blur is actually available.
.glass { background: rgba(255, 255, 255, 0.7); } /* readable fallback */
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
.glass {
background: rgba(255, 255, 255, 0.18);
backdrop-filter: blur(12px) saturate(160%);
-webkit-backdrop-filter: blur(12px) saturate(160%);
}
} With this in place, a browser that can't blur shows a solid, legible card instead of unreadable text over a busy background. That's the right default: the content works everywhere, and the polish layers on top where it's supported.
Where to take it next
The same four ingredients scale to navbars, modals and toolbars — anywhere a floating surface sits over
content. Try a darker tint (rgba(20, 20, 30, 0.3)) for a "smoked glass" version, or animate the
blur on scroll so a header frosts as the page moves beneath it.
Want to dial in the exact values without writing them by hand? The glassmorphism generator gives you live sliders and copies the finished CSS. For the backdrop itself, build one in the gradient generator.