Two ingredients that need each other
Glass gives a surface depth. Flow gives a page time. Most "glassmorphism" only does the first, which is why so much of it looks like frosted plastic — a blur over nothing in particular.
The two parts depend on each other. A translucent surface only looks like glass if what is behind it is doing something — drifting colour, a gradient that changes as you scroll, anything that makes the blur produce new information. Freeze the background and the same CSS becomes a grey box. There is a demo for exactly that below, because it is the part people skip.
- Blur Separates the surface from what is behind it. Too little and it looks dirty; too much and the depth cue disappears with the detail.
- Tint A thin white (or dark) wash. This is what carries your text contrast, so it is usually where accessibility goes wrong.
- Saturation Backdrop saturation above 100% is what makes glass look like glass rather than fog. It exaggerates the colour it is refracting.
- Edge A one-pixel gradient border, bright at one corner and gone at the other. This single line does most of the work of "specular".
- Lift A long, soft, downward shadow. It makes the surface sit above the page rather than printed on it.
Start with the background
No glass yet — just the field. A handful of coloured blobs, drifting slowly, heavily blurred. On its own it is just a background. It is there to give the glass something to bend.
Pull drift to zero and the field becomes a static gradient. Hold that thought — demo three is about what that does to the glass.
Five properties, moved one at a time
Now a panel over the same field. Every slider maps to one CSS declaration, and the block underneath prints the exact rule you are looking at. The usable range is narrower than you would expect: blur below about 10 px reads as smudged, above 50 px there is nothing left to refract, and tint above roughly 0.14 stops being glass and starts being a white card.
A panel with somewhere to be
Body text at the size this site actually uses, so the contrast you are judging is the contrast readers get.
This is the whole component. There is no image, no SVG filter and no library — a backdrop-filter, a translucent background, a gradient border and a shadow.
What happens when the background stops
Identical CSS on both panels. The only difference is whether the field behind them is moving. Press the button and watch the left one stop being glass — the blur is still there, the border is still there, and it now looks like grey plastic, because blurring something that never changes tells you nothing.
Same CSS
Nothing about this panel changed.
Same CSS
Nothing about this panel changed either.
This is also the argument for prefers-reduced-motion: if a reader turns motion off, the glass loses its reason to exist, so the fallback has to be drawn on purpose rather than being the same page standing still. On this site that means more tint and a firmer edge instead of a frozen field.
Flow also means pacing
The second half of the name has nothing to do with colour. A long argument delivered as one dense page asks the reader to hold everything at once; the same argument released a beat at a time lets the reader take each step having already agreed with the one before. Scroll position sets the pace.
A claim
Stated plainly, on its own.
The evidence
Arriving after the claim, not beside it.
The objection
Raised before the reader has to.
What follows
Which now costs nothing to accept.
The slider here does the scrolling for you. On a real page this is an IntersectionObserver adding one class — about six lines — and it is the cheapest way to make a long page easier to follow.
Checking the text is still readable
Translucent surfaces have an accessibility problem: the background behind your text is different at every scroll position, so checking the contrast once does not tell you much. The meter below actually measures it — it samples the actual pixels under the panel, composites your tint over them, and computes the WCAG ratio against the text colour.
Body copy over glass
This paragraph is the thing being measured, at the size and weight the site uses.
Measured contrast —
AA wants 4.5:1 for body text. The scrim is the fix that holds: a second, very slightly opaque layer sitting between the blur and the text, so the floor is set by the scrim rather than by whatever colour happens to drift past. You lose a little of the effect and get a floor you can count on.
Three things worth keeping
- Glass needs something moving behind it. If the background is static, use a solid card — it will look better and cost less. The effect is only worth the cost over something that moves.
- Tint looks like a styling choice, but it is an accessibility control. It decides whether the text is readable, so set it from the contrast meter rather than by eye.
- Reduced motion needs a designed fallback. Turning the field off just leaves you with the failure case from demo three, so the reduced-motion state has to be drawn on purpose.
Built as a standalone study. Everything here is invented — the field is five drifting circles and the sample text is placeholder. The whole page is one HTML file with no dependencies — a canvas, a few custom properties and about 200 lines of JavaScript.
Where this one went to work
The language above carries The GLP-1 Ripple — a signal study where the argument is released a section at a time and the figures sit on glass over a field that keeps moving. It is a much longer read, which is a fairer test of whether the effect still works after a while.
The other demo in this lab, the magic lens, looks at a different problem: how to show detail without throwing the page away.