Dev.to · 3 min read

Liquid Glass on the Web: 6 Ways to Build It with CSS and SVG

Liquid Glass on the Web: 6 Ways to Build It with CSS and SVG

Apple shipped Liquid Glass across iOS 26 and macOS, and suddenly every product I look at has a frosted panel floating over something. I spent a few weeks rebuilding the effect properly for a project, and most of what I found online stops at one line: backdrop-filter: blur(16px); Which gives you a gray rectangle. That's not what makes Apple's version look like glass, and figuring out the difference took me longer than it should have. So here are the six techniques I ended up with, roughly in order of how well they're supported, along with the things that wasted my time. 1. The plain glassmorphism card Everyone knows this one, but there are three parts to it and most implementations ship only the first. .glass-card { position: absolute; inset: 20%; border-radius: 16px; backdrop-filter: blur(16px) saturate(180%); -webkit-backdrop-filter: blur(16px) saturate(180%); background-color: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.12); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); pointer-events: none; } The saturate(180%) is the part I kept forgetting, and it turns out to be the whole trick. Blurring averages colors together, and averaging colors drains saturation out of them — so a pure blur comes out looking like dirty plastic rather than glass. Pushing saturation back up compensates. Drag it down to 100% in the pen above and you'll see the effect just die. The background tint matters for a similar reason. With a fully transparent background you get a blur but no surface — nothing reads as a physical pane sitting there. Something around 8% white is enough to suggest one without washing out whatever is behind it. Wrapped in React, so the numbers are adjustable: "use client"; type GlassCardProps = { blur?: number; saturate?: number; opacity?: number; radius?: number; }; export default function GlassCard({ blur = 16, saturate = 180, opacity = 0.08, radius = 16, }: GlassCardProps) { return ( ); } Two things that bit me here. An ancestor with overflow: hidden can clip the backdrop region, which produces a panel that looks like it's blurring nothing — I chased that for an hour before checking the parent. And backdrop-filter creates a containing block, so anything position: fixed inside it starts behaving oddly. Safari still wants the -webkit- prefix, but support is otherwise fine everywhere in 2026. 2. Making the edges fade Actual frosted glass doesn't stop at a crisp border, and once you notice that, hard-edged panels start looking cheap. The fix is mask-image. What makes it work is that the mask applies to the element including its backdrop filter — so the blur itself fades out, rather than you covering a blurred rectangle with a gradient and hoping nobody looks closely. const inner = 100 - feather; // feather: 0–80 const maskImage = `radial-gradient(ellipse at center, black ${inner}%, transparent 100%)`; One property, and the thing goes from "blurred rectangle" to something that looks like frost spreading across a surface. The catch is that the mask eats your border along with everything else, so if you want a visible edge you either keep the feather low or draw the border on a sibling element that isn't masked. 3. Blur that ramps up instead of starting all at once A single backdrop-filter is uniform across the element, which is wrong for the most common case: content passing under a sticky header, or fading out at the bottom of a hero image. There you want the blur to build, so text dissolves gradually rather than hitting a wall. CSS still has no gradient blur. What works is stacking several layers, each blurred slightly more than the last, each masked with a linear gradient that exposes only its own slice: const increment = 100 / divCount; const direction = position === "top" ? "to top" : "to bottom"; for (let i = 1; i

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More Programming & Dev News