Glassmorphism CSS is the frosted-glass look you see on macOS panels, iOS widgets, and modern dashboards: a translucent card that blurs whatever sits behind it. The whole effect comes down to two declarations, backdrop-filter: blur() and a semi-transparent background, layered over a colorful backdrop. Get those right and add a thin border highlight, and the glass reads as real.
Here is the part most generators skip. The card itself is the easy 20%. The reason your version looks dead while the dribbble shots look alive is almost always the background behind the glass, not the glass. This guide builds the effect from scratch, fixes the three things that make it look cheap, and covers the browser support you need to know before you ship.
What Glassmorphism CSS Actually Is#
Glassmorphism is a frosted-glass surface created by blurring the content behind an element rather than the element itself. You stack a low-opacity fill on top of backdrop-filter: blur(), add a faint light border, and let a vivid background show through. The blur plus transparency is what sells the "real glass" illusion.
That distinction matters. filter: blur() blurs the element you apply it to. backdrop-filter: blur() blurs everything painted behind it and leaves the element's own content sharp. Glassmorphism needs the second one, which is why a single wrong property name is the most common reason the effect "does nothing."
The look has three required ingredients and one optional flourish:
- A semi-transparent background (usually white or black at 10 to 25% opacity).
- A backdrop blur so the backdrop softens into a frost.
- A vivid, multi-color backdrop behind the card so there is something interesting to blur.
- A 1px inset border highlight that fakes the way light catches a glass edge.
The single biggest mistake is testing glassmorphism over a flat or white page. There is nothing to blur, so the card looks like plain low-opacity gray. Always build it over a gradient or a photo.
How to Build the Glassmorphism CSS Effect#
This is the full recipe. Follow the steps in order, because each one fixes a specific way the effect can look flat.
Step 1: Put a Vivid Gradient Behind the Card#
The backdrop does most of the visual work. A frosted card over a gray wall is gray frost. A frosted card over a magenta-to-cyan gradient is the look people actually want. Start with the background, not the card.
body {
min-height: 100vh;
background: linear-gradient(135deg, #7b2ff7 0%, #f107a3 50%, #00c6ff 100%);
}
Two or three saturated, contrasting hues blurred together produce the soft color bloom that reads as glass. If you are not sure which colors hold up once they are blurred, build the backdrop with a free CSS gradient generator and preview a few combinations before committing. Muddy or low-contrast gradients turn to sludge under blur, so test it.
Step 2: Add the Semi-Transparent Layer#
Now the card. Give it a fill that lets the backdrop through. White at low opacity works on most backgrounds; black at low opacity suits dark or neon scenes.
.glass {
background: rgba(255, 255, 255, 0.12);
border-radius: 16px;
padding: 2rem;
}
Use rgba() (or the modern rgb(255 255 255 / 12%) syntax) rather than the opacity property. Setting opacity fades the entire element, including its text and children. You only want the background translucent, never the content sitting on the glass.
Step 3: Apply the Backdrop Blur#
This is the line that turns a translucent box into frosted glass.
.glass {
background: rgba(255, 255, 255, 0.12);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border-radius: 16px;
padding: 2rem;
}
A blur radius of 8px to 16px hits the sweet spot. Below 6px the frost is barely visible; above 20px the backdrop dissolves into mush and you lose the sense that real content is behind the glass. Always pair the standard property with -webkit-backdrop-filter, because Safari still needs the prefix.
Step 4: Add the Border Highlight That Sells It#
Here is the detail nearly every generator leaves out, and it is the difference between "obviously CSS" and "looks like real glass." Real glass catches light on its top and left edges. You fake that with a faint, light, semi-transparent border.
.glass {
background: rgba(255, 255, 255, 0.12);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.25);
border-radius: 16px;
padding: 2rem;
}
The 1px light border reads as the bright rim of a glass panel. For an even more convincing edge, layer an inset highlight using box-shadow. The inset white line mimics light refracting along the inner edge:
.glass {
/* ...previous properties... */
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.2),
inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
That inset 0 1px 0 highlight is the secret ingredient. The outer shadow lifts the card off the page; the inset line gives the top edge that crisp glassy gleam.
Step 5: Tune Depth and Contrast#
With all four ingredients in place, adjust to taste:
- Opacity controls frostiness. Lower (8 to 12%) is more see-through; higher (18 to 25%) is milkier and more readable for text.
- Blur radius controls how soft the backdrop gets. More blur means more privacy frost and less visible detail behind.
- Outer shadow controls how far the card floats above the page. Soften and spread it for a more elevated feel.
- Border opacity controls how pronounced the glass rim looks. Brighter rim equals shinier glass.
A Complete Copy-Paste Example#
Putting every step together, here is a full working snippet you can drop into any project.
<div class="glass">
<h2>Frosted Glass Card</h2>
<p>Backdrop blur over a vivid gradient.</p>
</div>
body {
display: grid;
place-items: center;
min-height: 100vh;
background: linear-gradient(135deg, #7b2ff7 0%, #f107a3 50%, #00c6ff 100%);
}
.glass {
max-width: 360px;
padding: 2rem;
border-radius: 16px;
background: rgba(255, 255, 255, 0.12);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.25);
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.2),
inset 0 1px 0 rgba(255, 255, 255, 0.4);
color: #fff;
}
Swap the gradient for your own palette, drop the opacity if the text is hard to read, and you have a production-ready glass card. If you want to reuse the same hues across buttons, badges, and the page background, lock them in with a color palette generator for brand design so the whole UI stays consistent.
The Properties That Control the Look#
Use this as a quick reference when tuning a glass surface.
| Property | What it does | Typical range |
|---|---|---|
backdrop-filter: blur() | Frosts the content behind the card | 8px to 16px |
background: rgba() | Sets the translucent fill | 0.08 to 0.25 alpha |
border: 1px solid rgba() | Light rim that fakes a glass edge | 0.2 to 0.3 alpha |
box-shadow (outer) | Lifts the card off the page | soft, large, low alpha |
box-shadow (inset) | Crisp inner highlight on the top edge | inset 0 1px 0 white |
border-radius | Rounds the corners (glass is rarely sharp) | 12px to 24px |
You can combine backdrop-filter values too. Adding a touch of saturation makes the backdrop colors pop through the frost: backdrop-filter: blur(12px) saturate(160%). That saturation boost is a favorite trick for making the glass feel richer without changing the card's own fill.
Browser Support and the Gotchas Nobody Mentions#
backdrop-filter has solid support across modern Chrome, Edge, Safari, and Firefox, but there are real caveats that will bite you in production.
- Safari needs the prefix. Always ship
-webkit-backdrop-filteralongside the standard property. Without it, Safari renders a flat translucent box with no blur. - Firefox once gated it.
backdrop-filtershipped enabled in Firefox 103. Older builds had it behind a flag, so very old Firefox versions show the fill but no frost. For most audiences this is no longer a concern, but if your analytics show legacy Firefox traffic, plan a fallback. - It is GPU-expensive. Each
backdrop-filterelement forces the browser to re-sample and blur whatever is behind it. A page with dozens of blurred cards, or blur on a scrolling list, can drop frames on weaker devices. Use it on a handful of hero surfaces, not on every list item.
The clean fallback pattern is a feature query. Give everyone a readable opaque-ish card, then upgrade to true frost only where the browser supports it:
.glass {
background: rgba(255, 255, 255, 0.7); /* readable fallback */
}
@supports (backdrop-filter: blur(12px)) or (-webkit-backdrop-filter: blur(12px)) {
.glass {
background: rgba(255, 255, 255, 0.12);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
}
}
Accessibility warning: low-opacity white text on a busy gradient can fail contrast checks. Glass looks great in mockups and fails real users. Bump the fill opacity, darken the text, or add a subtle solid layer behind the text so it stays legible against any backdrop.
When to Use Glassmorphism (and When to Skip It)#
Glassmorphism shines on overlays that sit above rich content: navigation bars over a hero image, modals over a dashboard, widget cards over a gradient. The blur creates depth and keeps the layer below faintly visible, which is exactly the spatial cue it is meant to convey.
It is the wrong choice when there is nothing meaningful behind the card, when text legibility is critical (long-form reading, data tables), or when you need it repeated hundreds of times on one page. In those cases a solid card with a soft shadow performs better and reads more clearly.
Treat glass as a seasoning, not the whole meal. One or two glass surfaces over a strong gradient backdrop look premium. Twenty of them stacked on a flat page look like a bug.
Conclusion#
Glassmorphism CSS is genuinely simple once you see the full recipe: a vivid gradient backdrop, a semi-transparent fill, backdrop-filter: blur() with the WebKit prefix, and a 1px light border plus an inset highlight to fake the glass edge. The card is the easy part. The backdrop and the rim are what make it look real instead of dead.
Start by nailing the gradient, because everything else is layered on top of it. Build and preview your backdrop in the free CSS gradient generator, read the deeper guide to modern CSS gradient backgrounds for palette ideas, and then drop the glass card on top. When you are ready to ship the design as a flat image, a free SVG to PNG converter turns your exported vectors into the raster assets you need.
Frequently Asked Questions#
Why does my glassmorphism CSS look flat or gray? Almost always because there is nothing vivid behind the card. The frosted effect blurs the backdrop, so over a white or flat-gray page the result is just dull low-opacity gray. Put a saturated, multi-color gradient or a photo behind the glass and the look comes alive instantly.
What is the difference between filter blur and backdrop-filter blur?
filter: blur() blurs the element it is applied to, including its own text and children. backdrop-filter: blur() blurs only the content painted behind the element while keeping the element's content sharp. Glassmorphism needs backdrop-filter, which is why using the wrong one makes the effect appear to do nothing.
Does backdrop-filter work in all browsers?
It works in modern Chrome, Edge, Safari, and Firefox 103 and later. Safari requires the -webkit-backdrop-filter prefix in addition to the standard property, and very old Firefox builds had it behind a flag. Use an @supports feature query with an opaque fallback fill to cover browsers that lack support.
Why should I avoid the opacity property for glass cards?
The opacity property fades the entire element, including any text or buttons sitting on top of the glass, which makes content unreadable. Use an rgba() or rgb()/... background value instead so only the fill is translucent while the content stays fully opaque.
Is glassmorphism bad for performance?
It can be. Each backdrop-filter element forces the browser to re-sample and blur the pixels behind it, which is GPU-intensive. A few glass surfaces are fine, but blurring dozens of cards or applying it inside a scrolling list can drop frames on lower-end devices, so use it sparingly on hero elements.
How do I keep glassmorphism accessible? Watch text contrast. Low-opacity light text over a busy gradient often fails WCAG contrast checks. Increase the fill opacity, darken or bolden the text, or add a subtle solid layer behind the text block so it stays legible regardless of what color the backdrop shows through at that spot.



