← Back
[W] Writing

How Liquid Glass is rendered, and why reading it was the hard part

Frosted glass blurs whatever is behind it. Liquid Glass bends it.

That one change is why it looks alive, and it's why so much of the criticism was about reading it.

Drag the lens below. Scroll the content under it too.

Rendered pixel by pixel on a canvas, so it works in every browser. Push refraction up and watch the rim. The highlight moves as you drag, standing in for the phone tilting in your hand.

The middle of the lens looks like ordinary frosted glass. The edge is where it gets interesting. Shapes near the rim stretch and curve, the way they do at the edge of a glass of water.

Blur scatters, glass bends

The old material arrived with iOS 7 in 2013: translucent layers that blurred the content behind them. A year later, iOS 8 gave developers the same thing as UIVisualEffectView, with blur and vibrancy effects.

A blur is an average. Every pixel becomes a mix of its neighbours, so detail spreads out and the surface reads as a soft, flat pane.

Apple described the difference in its WWDC25 session Meet Liquid Glass: "Whereas previous materials scattered light, this new set of materials dynamically bends, shapes, and concentrates light in real time." Apple calls this lensing.

Frosted glassBlurs the backdrop. Has a fixed light or dark look. The shape is just a rounded rectangle.
Liquid GlassBends the backdrop at the edges, catches highlights that move, adjusts its tint and shadow to what's behind it, and keeps its corners concentric with the device.
All of the second row is from Apple's own descriptions. How Apple renders it internally isn't public.

Refraction is a displacement map

Think about a thick slab of glass with rounded edges, lying on a page.

Look straight down through the flat middle and you see the page directly underneath. Look down through the curved rim and the surface is tilted, so your line of sight bends inward. You see a bit of the page that is further in than where you're looking.

Page behind the glass Flat middle: no offset Rim: offset
Grey lines pass straight through. Red lines hit the curved rim, bend inward and land further in. The dashed line is where they'd have landed without the glass.

That's the whole idea, and on a screen you don't need to trace any rays. You only need to answer one question for every pixel inside the shape: where in the background should this pixel copy its colour from?

The answer is a displacement map. In the middle, the offset is zero. Near the rim, the offset grows, and it points inward.

// d: how far this pixel is inside the edge, in px
// (nx, ny): the outward direction at the nearest edge
const t = Math.max(0, 1 - d / bezel); // 0 in the middle, 1 at the rim
const shift = strength * t * t;       // grows towards the edge
const from = { x: x - nx * shift, y: y - ny * shift };

That's the code the demo runs. bezel is how wide the curved band is, and squaring t keeps the middle calm and makes the bend steep right at the edge, like a real rounded rim. The demo blurs the background first, then samples it through this map.

The distance and the direction come from a signed distance function for a rounded rectangle. It's a short formula that tells you, for any point, how far it is from the shape's edge and which way the edge faces.

Light, tint and shadow

Bending is what makes it look like glass. The rest makes it look like an object.

Highlights. Apple's session says light sources "shine on the material producing highlights that respond to geometry", and that "in some cases, the lighting responds to device motion." In the demo it's a thin band on the rim, bright where the edge faces the light and fainter on the opposite side.

Adaptive shadow and tint. The same session says the glass "increases the opacity of its shadow when it is over text" and lowers it over a plain light background. Small elements like tab bars also flip between light and dark depending on what's behind them.

Concentric shapes. Apple's announcement says controls "now fit perfectly concentric with the rounded corners of modern hardware and app windows." The maths is one line. Inset a shape by some padding, and its radius has to shrink by the same amount, or the gap between the two curves won't stay even.

const inner = Math.max(0, outerRadius - padding);

Why reading got hard

Contrast is a ratio between two colours. WCAG asks for at least 4.5:1 for normal text.

On a solid button, both colours are yours, so you check it once. On glass, one of them is whatever happens to be behind the glass. Scroll, and your contrast changes.

Scroll the content under the toolbar, or jump to a section. The label flips between black and white like the system glyphs do. Then try Tinted on the busy section.

The readout shows two numbers, and the difference between them is the real problem.

Against the average colour behind the label, busy content often passes. But the average hides the stripes and letters that happen to sit behind your text. Look at the worst tenth of the pixels and the number can drop a long way. That's the moment a label becomes hard to read, even though the average says it's fine.

Apple's own guidance already says this. Its Clear variant "is permanently more transparent", and "to provide enough legibility for symbols or labels, it needs a dimming layer to darken the underlying content."

What iOS 27 changed

At WWDC26 Apple kept the material and changed how readable it is. As reported by MacRumors, MacStories and iDrop News:

  • A transparency slider. It's in Settings under Appearance, and runs from clear to tinted. MacStories describes it as covering any level between More Clear, Default and More Tinted. It's the Tinted button in the second demo, turned into a continuous range.
  • A darkened edge and brighter specular highlights, to separate the glass from what's behind it. That's the edge darkening slider in the first demo.
  • A uniform toolbar when content scrolls under floating bars, applied automatically to standard toolbars and adjustable through the scroll edge effect APIs.

All three do the same job. They put back some of the control over contrast that glass gave away.

Building it on the web

You can get close in CSS. Blur works in every current browser with backdrop-filter. Refraction needs an SVG filter.

<filter id="lens">
  <feImage href="map.png" result="map" />
  <feDisplacementMap in="SourceGraphic" in2="map" scale="40"
    xChannelSelector="R" yChannelSelector="G" />
</filter>

<style>
  .glass { backdrop-filter: blur(4px); }
  .glass.lens { backdrop-filter: url(#lens) blur(4px); }
</style>

feDisplacementMap moves each pixel by scale × (channel − 0.5), so the map image stores the same offsets as the code above. Red holds the x offset and green holds the y offset, and mid-grey means don't move.

There are two catches.

Support. As of November 2026, SVG filters inside backdrop-filter only work reliably in Chromium. WebKit's bug 245510 is still open, with patches proposed, and Firefox drops filters like this one (bug 1961378). CSS.supports won't save you, because it checks that the syntax parses, not that anything renders. So treat refraction as decoration, and make sure the blur alone is readable.

Cost. A backdrop filter reads back whatever is behind the element and filters it again whenever that changes. While the page scrolls, that's every frame. The first demo shows the count. Even a small lens re-reads tens of thousands of pixels each time.

That's why it's an approximation of the look, not Apple's implementation. Apple controls the whole rendering pipeline and hasn't published how it works. The web gets a filter on a box.

What I'd keep from all of this is simple. Glass borrows its appearance from whatever is behind it. Put text on it and you've let the content decide your contrast. So design the label for the worst pixel behind it, not the average.

Next