CSS Glassmorphism: Recipe and Pitfalls

Glassmorphism is a frosted-glass panel look built from a small set of CSS properties working together: a blurred backdrop, a translucent fill, a subtle border and a soft shadow. This post breaks down the exact recipe, the performance cost of blurring, and the readability failures that show up when the effect is applied without checking contrast.
The core recipe
A glassmorphism panel is built from four layers working together: a background-filter that blurs whatever is behind the element, a semi-transparent background colour on the element itself, a thin light border, and a soft drop shadow to lift the panel off the page. None of these alone produces the effect; it is the combination that reads as frosted glass.
A minimal version looks like this: background: rgba(255, 255, 255, 0.15), backdrop-filter: blur(12px), border: 1px solid rgba(255, 255, 255, 0.3), and box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2). Adjusting the blur radius and the opacity of the background colour changes how strong or subtle the glass effect looks.
backdrop-filter: blur and saturate
backdrop-filter applies filter effects to whatever is rendered behind an element, rather than to the element itself, which is what makes the frosted look possible over a photo or gradient background. blur() is the main function used for glass panels, typically between 8px and 20px depending on how much of the background detail you want to still be visible.
Adding saturate() alongside blur, such as backdrop-filter: blur(12px) saturate(180%), boosts the colour intensity of whatever is showing through, which counteracts the way blurring tends to wash colours out and gives the panel a more vivid, glass-like appearance rather than a flat grey haze.
Background layers and translucency
The background colour behind the blur needs enough opacity to read as a distinct panel, but not so much that it blocks the blurred content entirely. Values between 10% and 25% opacity on a white or near-white colour work well on most backgrounds, while dark interfaces often use a translucent dark colour instead so the glass tint matches the surrounding theme.
Layering a very subtle gradient inside the same background, going from a slightly lighter tone at the top to a slightly darker one at the bottom, adds depth without needing an extra image, since it mimics the way light falls on real glass.
Border and inner highlight
A one pixel border in a light, semi-transparent colour defines the edge of the panel, which is important because a pure blur with no border can look like a smudge rather than a distinct object. On light backgrounds this border can be a light white at low opacity; on dark backgrounds a lighter grey often reads better than pure white.
Some implementations add a second inset box-shadow as an inner highlight along the top edge, simulating the way light catches the top of real glass. This is optional, but it adds a noticeable amount of realism for a very small amount of extra CSS.
Shadow depth
The box-shadow separates the panel from the page and gives it the sense of floating above the background rather than sitting flush against it. A larger blur radius on the shadow, combined with a low opacity, produces a soft ambient shadow that suits the glass look better than a sharp, high-contrast shadow, which tends to look heavier and less airy.
Keep the shadow colour close to black at low opacity rather than tinted, since a coloured shadow tends to fight with the translucent tint already coming from the panel background.
Performance cost and compositing
backdrop-filter is expensive to render because the browser has to continually recompute the blur of everything behind the element, including on scroll or when content behind it animates. A single glass panel over a static background is usually fine, but many panels stacked on a page, or a glass panel over a scrolling list, can cause visible frame drops on lower-powered devices.
Where possible, apply backdrop-filter to elements that do not move or resize frequently, and avoid nesting multiple blurred panels on top of each other, since each one adds its own compositing cost.
Browser support: Safari prefix and Firefox history
Safari required the -webkit- prefix for backdrop-filter for a long time, so a robust declaration still includes both -webkit-backdrop-filter and the unprefixed backdrop-filter, in that order, so the prefixed version is used first where needed and the standard version is picked up everywhere else.
Firefox did not support backdrop-filter for several years after Chrome and Safari did, which meant glass effects silently fell back to a flat, unblurred background colour in Firefox. Current versions of Firefox do support it, but if you need to support very old versions, plan for the flat fallback rather than assuming the blur will always render.
Contrast and readability failures
The most common failure with glassmorphism is text placed directly on the translucent panel becoming hard to read, because the panel opacity was tuned for looks rather than checked against whatever happens to be behind it at runtime. A panel that looks fine over a plain colour background can fail badly over a busy photo or a bright gradient.
Test contrast against the worst-case background the panel might sit over, not just the one used in the design mockup, and consider adding a slightly more opaque background specifically behind text elements if the surrounding photo content is unpredictable.
Fallbacks with @supports, and light versus dark backgrounds
Wrapping the effect in @supports (backdrop-filter: blur(1px)) lets you provide a plain, more opaque background as the default and only apply the translucent blur when the browser can actually render it, avoiding the see-through-but-not-blurred look that happens when backdrop-filter is unsupported but the low-opacity background still applies.
The same base recipe needs different tuning depending on whether it sits on a light or dark background: light backgrounds generally need a white-tinted glass with a darker shadow, while dark backgrounds need a dark-tinted glass with a lighter border to remain visible, since a white-tinted panel on a dark background can look washed out rather than glass-like.
For a ready-made set of tuned values rather than tuning the recipe from scratch, the /ui-assets section includes glassmorphism presets that already balance blur, opacity and border for both light and dark themes.
A worked example: a login card over a photo background
A login form placed over a full-bleed photo background is one of the most common glassmorphism use cases. The card gets background: rgba(255, 255, 255, 0.12), backdrop-filter: blur(16px) saturate(180%), border: 1px solid rgba(255, 255, 255, 0.25), border-radius around 16px for the soft rounded look typically paired with this style, and box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25). Form labels and input placeholder text inside the card use a slightly higher contrast colour than the same design would use on a plain white background, since the blurred photo behind the card reduces effective contrast even with the panel tint applied.
Because the photo background can vary between page loads or between light and dark hero images on different pages, adding a semi-transparent dark overlay behind the entire hero section, independent of the card itself, keeps the range of possible backdrop colours the card blurs over within a predictable, testable range.
FAQ
Why does the glass effect disappear completely in one browser? backdrop-filter is either unsupported or gated behind the -webkit- prefix in that browser; check that both the prefixed and unprefixed declarations are present, and confirm the fallback background inside @supports is not accidentally too opaque, which would mask a working blur underneath it.
Can I animate the blur amount, for example on hover? Yes, but treat it as an expensive animation; test it on lower-powered hardware first, since animating backdrop-filter triggers continuous recomputation of the blur for the whole duration of the transition rather than a single one-off calculation.
Does glassmorphism work well with dark mode toggles? It works, but the panel's background and border colours need their own light and dark variants rather than a single fixed rgba value, since a value tuned for a light backdrop typically looks washed out or muddy once the surrounding page switches to a dark theme.
Questions about the tools in this guide
Short answers about the hubs this article touches, each linking straight to the tool.