Skip to content
WebTricks

Liquid glass in CSS — frost, rim, sheen and real refraction

How to build an Apple-style liquid glass effect with pure CSS, and how far you can push it with an SVG displacement filter.

Apple’s “liquid glass” look is everywhere now. The good news: most of it is plain CSS. The catch: the bending refraction — where the background warps as it passes through the glass — needs an SVG filter that, for now, only Chromium ships. Here’s both layers, so you can take the part that fits your support target.

1. The cross-browser core

Frosted glass is backdrop-filter, but liquid glass reads as a thick, lit pane. Three ingredients do that:

.liquid-glass {
  background: rgba(255, 255, 255, 0.10);
  backdrop-filter: blur(8px) saturate(180%) brightness(1.1);
  -webkit-backdrop-filter: blur(8px) saturate(180%) brightness(1.1);

  /* refractive rim: a strong top highlight + softer ones on the other edges */
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.25),
    inset 0 1px 1px rgba(255, 255, 255, 0.55),
    inset 0 -1px 1px rgba(255, 255, 255, 0.30),
    inset 1px 0 1px rgba(255, 255, 255, 0.20),
    inset -1px 0 1px rgba(255, 255, 255, 0.20);
}

Add a diagonal sheen with a pseudo-element so the surface looks glossy:

.liquid-glass::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;          /* below the text, above the tint */
  border-radius: inherit;
  background: linear-gradient(135deg,
    rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0.08) 28%, transparent 58%);
  mix-blend-mode: screen;
}

The element needs position: relative and isolation: isolate so the negative z-index stays inside its own stacking context. The full, control-driven version is in the liquid glass card snippet — and the simpler flat variant is the glassmorphism card.

One rule for any glass effect: it only shows over a busy, colorful background. Over a flat fill the blur has nothing to sample.

2. Real refraction with SVG (Chromium only)

To make the backdrop actually bend, displace it with an SVG filter. Procedural noise from feTurbulence drives a feDisplacementMap:

<svg width="0" height="0" style="position: absolute">
  <filter id="liquid" x="0" y="0" width="100%" height="100%">
    <feTurbulence type="fractalNoise" baseFrequency="0.008 0.008"
                  numOctaves="2" seed="4" result="noise" />
    <feGaussianBlur in="noise" stdDeviation="2" result="blurred" />
    <feDisplacementMap in="SourceGraphic" in2="blurred" scale="60"
                       xChannelSelector="R" yChannelSelector="G" />
  </filter>
</svg>
@supports (backdrop-filter: url(#liquid)) {
  .liquid-glass { backdrop-filter: blur(2px) url(#liquid); }
}

The red channel of the noise shifts pixels horizontally, the green channel vertically; scale is how far they move. Swap the procedural feTurbulence for an feImage pointing at a hand-painted PNG when you want a specific, repeatable distortion instead of random noise.

Caveat: using an SVG filter as input to backdrop-filter works in Chromium-based browsers but not yet in Safari or Firefox, which is why it’s gated behind @supports. Heavy filters also cost FPS on low-end devices — keep them off large scrolling surfaces.

Further reading

These walkthroughs go deeper on the displacement-map approach: LogRocket and this Habr article.

Want to theme it live? Open the liquid glass card snippet and drag the controls. Now at 32 tools and 25 snippets — browse snippets or subscribe via RSS.