Liquid Glass, but in CSS

Author Avatar Pup Atlas
Published on June 19th, 2025
This past week marked the start of WWDC25, Apple's yearly developer conference where they reveal new platforms, technologies, and (most relevant here) design languages. During the presentation they released their newest iteration, dubbed Liquid Glass. I have a lot of thoughts on this new language, but my immediate thought while I was watching the presentation was "I wonder if CSS can do that". It turns out, yes, with great effort, it can.
Liquid Glass
A note about compatibility
This effect is dependant on CSS SVG filter support, and will not function properly in browsers other than Chrome.
Light Glass
Example
Breaking Down the Effect
Scouring through the videos available from Apple, and by downloading the beta software myself on my devices, I was able to start breaking down some of the layers that make up the Liquid Glass effect.
Specular Highlights
Highlights on the edges of the glass help to suggest the illusion of depth, and imply the smoothness of the shape. This is important for making the element look like a physical, tactile object— rather than a flat shape on a screen. This should be the easiest element to replicate, since we can approximate a round shape fairly easily with a series of inset
box-shadow
properties.
CSS
I'm using two shadows for the top left corner, and two for the bottom left. This allows for the shadow to sharply increase in intensity as it reaches the edge of the shape, simulating the fresnel effect.
Blur
This one's easy, we can use the
filter
prop to apply effects onto our dom element. In this case though, we want to apply the effect to the content behind our element, rather than the element itself— so we'll need to use the
backdrop-filter
instead.
CSS
😀😃😄😁😆😅😂🤣🥲🥹☺️😊
Color Filters
The Liquid Glass demos all show the material adjusting the color that passes through it, specifically decreasing the contrast, and boosting saturation. This has the effect of making anything behind the glass look more vibrant. We can use the same technique as above to adjust the color of light that passes through the glass.
CSS
😀😃😄😁😆😅😂🤣🥲🥹☺️😊
Simulating Refraction
Next, we need to simulate the way that round pieces of glass warp light that passes through them. This layer also marks the first time we need to distort content underneath the glass, rather than just painting over top of it. To accomplish this, we can use the
filter
CSS property in conjunction with an SVG filter injected alongside the component. This filter will consist of a number of stages that all build on each other to create a cohesive refraction effect.
Edge Distortion
To distort the objects under our shape, we'll need to generate a distortion map. This will tell the browser how much to move each pixel when performing the distortion. In our case, we want to bulge out all the pixels towards the center of our panel, and squish them towards the edges. Let's start by generating a blank distortion map that we can build off of as an SVG.
HTML
SVG Identity Map
The final result is a gradient going from 0-1 in the red channel horizontally, and 0-1 in the blue channel vertically. You can think of each pixel having an X and Y coordinate for where it's supposed to go in the final image. Right now, everything is lined up, meaning the pixel in the dead center of the image has an XY value of (0.5, 0.5), meaning that it would not be moved at all. But we can influence these colors to be different from their location in the image, to tell the browser where each source pixel should be moved.

Now that we've generated this base map (normally called an "identity map" in graphics lingo), we can use normal SVG shapes and blend modes to adjust the color of parts of the map. In this case, we want to make the XY values rise slower towards the center, and more sharply towards the edges.
Compressing the Edges
To achieve the stretch we're looking for, we can simply adjust the gradient ramp to compress the space around the edges. In this example, we're effectively squishing 30% of the vertical and horizontal frame into just 5% of the space on each edge.
SVG Distortion Maps
To use our new SVG as a distortion map, we'll need to first convert it to a data url, to let us use it in the
<feImage />
element. To do this, we can write a simple helper function to convert our HTML into a URI-encoded string, and prepend the data url prefix.
Typescript
Now that we've got our string, we can start to build an SVG effect chain. We'll make our filter 40 pixels larger than our target element, and offset it by -20 pixels to allow our effect to overhang our target element, which allows the distortion have some extra room before clipping the edge of our shape.
HTML
Ripple Distortion
Next, we'll want to simulate the ripple distortion present in larger pieces of glass. This is fairly straightforward, and the SVG filter spec already has a basic turbulence texture built in, so we can plug that into another
<feDisplacementMap />
layer, just as before.
HTML
Chromatic Aberration
Lastly, we'll want to simulate the chromatic aberration of light as it passes through our element. This is when some colors of light travel further than others. There's no simple way to do this with SVG filters, but what we can do is take three copies of our existing image, filter out different colors for each copy, offset them by different amounts, and blend them back together.
HTML
Now that we've created all our effects, we can layer them in the SVG filter, and apply them via the
filter: url(#filterId);
syntax to apply them to a DOM element— and that's it! We've successfully created a take on liquid glass. This approach isn't fully cross-browser, which is unfortunate.
Caveats
After much effort, I've not found a way to recreate this effect in Safari/Firefox. For now, you must remove the SVG filter from the
filter
CSS prop from the filter chain in these browsers, leaving just the blur effect, and the drop shadows. This is a reasonable fallback, and shouldn't fundamentally break any UI, but it's not ideal.
This approach also takes a non-insignificant amount of GPU brunt, and more than one or two glass elements can quickly slow the tab down— especially if they animate in any way. Glass elements are (currently) only really viable for hero/feature elements, rather than a full UI.
Credits
Most of the approach described in this article were built directly overtop of the methods described in the excellent Smashing Magazine article "A Deep Dive Into The Wonderful World Of SVG Displacement Filtering".
Loading Link Content
Loading Link
The Apple Liquid Glass documentation was also excellent for describing the basic components of the effect, and some considerations for usage. It's definitely worth a quick read.
Loading Link Content
Loading Link
Pup Atlas!