Frosted Glass UI in Pure CSS (Glassmorphism)
Create high-performance frosted glass card components with backdrop-filter blur, border contrast, and hardware acceleration in pure CSS.
CSS Glassmorphism Generator
100% In-browser execution. Zero server uploads, instant results, free forever.
- 1. What Glassmorphism Is, in Two CSS Properties
- 2. How backdrop-filter Differs From filter
- 3. The Translucency Budget: Why 0.12 and Not 0.6
- 4. The Hairline Border That Sells the Illusion
- 5. What It Costs: Compositing, Repaint, and Scroll
- 6. The Accessibility Problem Nobody Mentions
- 7. Support, Prefixes and a Fallback That Degrades Well
- 8. Frequently Asked Questions (FAQ)
What Glassmorphism Is, in Two CSS Properties
Glassmorphism is a surface treatment that makes an element look like frosted glass laid over the page behind it. Despite the number of tutorials that reach for images, gradients and pseudo-elements, the effect reduces to two properties working together:
backdrop-filter: blur(12px)— blurs whatever is painted *behind* the element, not the element itself.background: rgba(255, 255, 255, 0.12)— a background that is mostly transparent, so the blurred backdrop remains visible through it.
Everything else — the hairline border, the shadow, the subtle inner highlight — is polish on top of those two lines. If you take nothing else from this article: backdrop-filter does nothing visible unless the element's own background is translucent. That single misunderstanding accounts for most "backdrop-filter is not working" questions.
A minimal, correct glass card is short enough to read in one go:
.glass {
background: rgba(255, 255, 255, 0.12);
backdrop-filter: blur(12px) saturate(140%);
-webkit-backdrop-filter: blur(12px) saturate(140%);
border: 1px solid rgba(255, 255, 255, 0.22);
border-radius: 16px;
}
How backdrop-filter Differs From filter
filter and backdrop-filter look similar and behave nothing alike.
filter: blur(12px) takes the element and its contents — text, icons, children — and blurs all of it. Applied to a card, the card's own label becomes unreadable. This is almost never what a glass surface wants.
backdrop-filter: blur(12px) leaves the element's contents perfectly sharp and instead filters the backdrop image: the composite of everything already painted beneath the element, clipped to the element's own border box and rounded corners.
The browser builds that backdrop image in a distinct step. It takes a snapshot of the painted result behind the element, applies the filter chain to that snapshot, and draws the element's own background and contents on top. Because the snapshot is taken from what is *already painted*, backdrop-filter cannot see sibling elements that paint later in the same stacking context, and it cannot see anything outside the element's clip.
That ordering explains a second common confusion: nesting two glass panels does not compound the blur the way people expect. The inner panel filters a backdrop that has already been flattened by the outer one, so the second blur operates on an image that is already smooth. Stacking them mostly costs performance and returns very little.
The filter chain accepts more than blur, and a small amount of saturate() is what separates a convincing glass surface from a grey smear. Blurring averages neighbouring pixels, which pulls colours toward the mean and drains the backdrop of vibrancy. Pushing saturation back up to roughly 140–180% restores the colour that the blur removed:
backdrop-filter: blur(14px) saturate(160%) brightness(105%);
The Translucency Budget: Why 0.12 and Not 0.6
The background alpha is the single value that decides whether a surface reads as glass or as tinted plastic. It is worth choosing deliberately rather than nudging until it looks acceptable.
At alpha 0.05–0.15, the backdrop dominates. The card reads unmistakably as glass, and it inherits the colour of whatever is behind it. This is the right range for decorative panels over a photograph or a colourful gradient.
At alpha 0.2–0.35, the surface begins to assert its own colour. The backdrop is present but subordinate. This is the practical range for panels that must hold readable body text over an unpredictable background.
Above alpha 0.5, you no longer have glass. You have a translucent panel, and the blur is doing almost no visible work while still costing a compositing pass. If you find yourself here for contrast reasons, delete the backdrop-filter and use an opaque background — you will get the same appearance and drop the GPU cost entirely.
The direction of the tint matters as much as the amount. On dark backdrops, a white tint (rgba(255, 255, 255, 0.1)) lifts the surface forward. On light backdrops, a white tint disappears and a dark tint (rgba(15, 23, 42, 0.08)) is what creates separation. A card that looks correct in one theme and muddy in the other usually has the tint colour, not the alpha, set wrong.
The Hairline Border That Sells the Illusion
Real glass catches light along its edges. A flat translucent rectangle does not, which is why an unbordered glass card tends to look like a rendering artefact rather than a material.
The convention is a one-pixel border a few percent brighter than the fill:
border: 1px solid rgba(255, 255, 255, 0.22);
For a more convincing edge, separate the top edge from the rest. Light in most interface metaphors arrives from above, so the top border should be brightest and the bottom nearly invisible. An inset box-shadow produces this without extra markup:
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.28),
inset 0 -1px 0 rgba(255, 255, 255, 0.06),
0 12px 32px rgba(0, 0, 0, 0.22);
The third shadow in that list is the outer drop shadow, and it is doing something specific: it darkens the backdrop immediately beneath the card, which increases the contrast between the card's edge and its surroundings. Glass panels without a drop shadow tend to float ambiguously; the shadow is what places them in front of the page rather than embedded in it.
Note that border-radius is honoured by the backdrop clip. A 16px radius produces a blurred backdrop with 16px rounded corners automatically — you do not need overflow: hidden on a wrapper, and adding one can create its own stacking-context surprises.
What It Costs: Compositing, Repaint, and Scroll
backdrop-filter is a compositor-level operation, which is both why it is fast enough to ship and why it can become the most expensive thing on a page.
Applying it promotes the element to its own compositing layer. The browser must then, for every frame in which the backdrop changes, re-read the pixels behind the element, run the filter chain over them, and recomposite. Over a static background that work happens once. Over a backdrop that moves — a scrolling list, a video, an animated gradient — it happens every frame.
The practical consequences are worth stating plainly:
- Area is the cost driver. Blur cost scales with the number of backdrop pixels, not with the complexity of the content. One full-screen glass overlay is far more expensive than six small glass cards.
- Blur radius matters less than area, because most implementations approximate Gaussian blur with a fixed number of downsample-and-box passes rather than a kernel that grows linearly with the radius.
- Animating a glass element's position or size forces the backdrop to be re-filtered every frame. Animating its
opacityortransformis considerably cheaper than animatingwidth,toporbackdrop-filteritself. - Avoid glass on elements pinned over a scrolling region unless you have measured it on a low-end device. This is the single most common cause of janky scroll in otherwise well-built interfaces.
A useful discipline: treat backdrop-filter as you would a large shadow or a full-page gradient. One or two per viewport is unremarkable. A dozen, or one covering the whole screen during a scroll, deserves a measurement before it ships.
The Accessibility Problem Nobody Mentions
A glass surface has, by design, an unpredictable background. That is a direct problem for text contrast, because WCAG contrast ratios are computed against the colour actually behind the glyphs — and on a glass card, that colour is whatever happened to be underneath.
Text that passes at 7:1 over the dark part of a photograph can fall below 3:1 over the bright part of the same photograph, in the same card, at the same moment. No single colour choice fixes this, because there is no single background colour.
Three mitigations actually work:
- Raise the fill alpha under text. The blurred backdrop can stay decorative around the edges while the text sits on a region with enough opacity to stabilise contrast — roughly 0.35 and up for body copy.
- Add a contrast floor with a gradient. A subtle vertical gradient in the card's own background, darker where the text sits, sets a known worst case without making the whole surface opaque.
- Constrain what can appear behind glass. If the backdrop is a controlled gradient rather than user-supplied imagery, the worst case is knowable and testable.
Honesty about the limit: if your glass panel must carry body text over arbitrary user images, glass is the wrong material. The effect is best used for chrome, navigation and decorative surfaces where the text is short, large and high-weight.
Support, Prefixes and a Fallback That Degrades Well
backdrop-filter is supported in current Chrome, Edge, Firefox and Safari. Two details still matter in production.
Safari has required the -webkit- prefix for this property far longer than most, and older Safari versions on iOS still do. Ship both declarations, prefixed first:
-webkit-backdrop-filter: blur(12px) saturate(160%);
backdrop-filter: blur(12px) saturate(160%);
For browsers without support, the failure mode is not a broken layout — it is a card whose background is 12% white over a sharp, busy backdrop, which is usually illegible. Feature-query the enhancement rather than the fallback, so the readable version is the default:
```css .glass { background: rgba(17, 24, 39, 0.82); /* opaque enough to read, always */ }
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) { .glass { background: rgba(255, 255, 255, 0.12); -webkit-backdrop-filter: blur(12px) saturate(160%); backdrop-filter: blur(12px) saturate(160%); } } ```
Written this way, a browser that cannot blur shows a solid, legible card, and only browsers that can blur opt into translucency. This ordering is the opposite of what most snippets do, and it is the reason those snippets break on older devices.
One further consideration: users who enable Reduce Transparency in their operating system are asking, explicitly, for less of this. There is no dedicated media query for it, but prefers-reduced-transparency is shipping in current browsers and is worth honouring where available.
The glassmorphism generator emits the blur, tint, border and shadow together with the @supports fallback described above. For the backdrop underneath it, the gradient studio is the companion tool.
Frequently Asked Questions (FAQ)
What is glassmorphism in CSS?
Glassmorphism is a CSS surface style that makes an element look like frosted glass over the page behind it. It is produced by combining a mostly transparent background such as rgba(255, 255, 255, 0.12) with backdrop-filter: blur(12px), plus a hairline light border and a soft drop shadow. The blur applies to the backdrop behind the element, so the element's own text stays sharp.
Why is my backdrop-filter not working?
The most common cause is an opaque background on the same element. backdrop-filter blurs what is behind the element, so if the element's own background is fully opaque it hides the blurred result completely. Set a translucent background such as rgba(255, 255, 255, 0.12). The second most common cause is a missing -webkit-backdrop-filter declaration, which older Safari versions still require.
What is the difference between filter and backdrop-filter?
filter blurs the element and everything inside it, including its own text. backdrop-filter leaves the element's contents sharp and blurs only the backdrop painted behind it, clipped to the element's border box and border radius. For a glass card you want backdrop-filter; filter would make the card's own label unreadable.
Does backdrop-filter hurt performance?
It can. backdrop-filter promotes the element to its own compositing layer, and the browser re-filters the backdrop pixels on every frame in which that backdrop changes. Cost scales with the area covered rather than the blur radius, so one full-screen glass overlay is much more expensive than several small cards. The costly case is a glass element pinned over a scrolling region, which should be measured on a low-end device before it ships.
How do I keep text readable on a glass card?
Raise the background alpha under the text to roughly 0.35 or higher, add a subtle gradient in the card's own background so there is a known worst-case contrast, and constrain what can appear behind the panel. If the glass must carry body text over arbitrary user-supplied images, contrast cannot be guaranteed and an opaque surface is the correct choice.
Do I still need the -webkit-backdrop-filter prefix?
Yes, if you support older Safari and older iOS versions. Current Chrome, Edge, Firefox and Safari all support the unprefixed property, but the prefixed form is still required on a meaningful number of iOS installs. Declare -webkit-backdrop-filter first, then backdrop-filter, and wrap the translucent styling in an @supports query so unsupported browsers keep a solid, legible background.
Related Guides & Solutions
Neumorphism in CSS: Soft UI Shadows That Work
Smooth CSS Keyframe Animations Without a Library
Ready to use CSS Glassmorphism Generator?
Execute this workflow privately on your device right now without creating an account or paying for cloud API credits.