Shadow
The contact shadow that sets glass into the page.
Glass with no shadow floats flat on the page. LiquidGlassShadow is the soft dark band that hugs the rim and pools underneath, so the surface reads as sitting in the page rather than pasted on it. Every component that ships with a tuned look already wears one.
Where it goes#
Almost always on the style, as shadow — the lens then wraps itself in it, at its own corner radius and its own live stretch, and a visibility: false takes the shadow away with the glass:
LiquidGlassLens(
style: const LiquidGlassStyle(
shadow: LiquidGlassShadow(blur: 3.5, opacity: 0.2),
),
child: myContent,
)It is also a plain widget, and as a widget it is a parent of the glass — never its child:
LiquidGlassShadow(
child: LiquidGlassLens(style: myStyle, child: myContent),
)How the shape is made#
The shadow is cast by a ring, not by the surface itself: an outer capsule pushed out, minus an inner one pulled in, so only a band straddling the rim casts anything and the middle stays clear. That ring is displaced downward by offset (blur + 2 by default) and blurred — the upper arc lands just inside the top rim, the lower arc entirely below the surface. One ring gives both the rim contact and the drop beneath. It composites with BlendMode.multiply, so it darkens what is under it instead of laying flat grey over it.
| Parameter | Default | What it does |
|---|---|---|
blur | 3.5 | Blur radius, and the vertical thickness of the casting ring. |
opacity | 0.2 | How dark it lands. |
color | Colors.black | The colour before opacity is applied. |
offset | blur + 2 | Downward displacement of the ring. Null takes the default. |
cornerRadius | null | The surface’s rest corner radius. Null makes it a capsule. On style.shadow the lens fills in its own shape’s radius. |
scale | (1, 1) | The outline stretch — deformed size ÷ rest size — so the ring follows an elliptical cap under a squashed lens. |
inset | 0 | Tucks the shadow inside the glass, so the surface overhangs it. Reads as a tighter contact on a small control, where a full-size halo looks like a glow. |
visible | true | False paints nothing and leaves the child untouched, so it toggles without changing the tree’s shape. |
insideGlass | true | Whether the ring is drawn under the glass outline. False keeps only what falls outside it — see below. |
Keeping it out of the glass#
The ring is painted behind the glass, and the glass reads what is behind it. With insideGlass: true (the default) that is the contact look: the upper arc darkens the inside of the rim. On a lens that refracts strongly — a wide refraction band, or a magnification below 1 — the rim can pull that shadow further in, and it shows as a dark band inside the edge.
insideGlass: false clips the ring to the outside of the outline and paints it over the glass instead of under it. The drop beneath looks the same, but the glass never sees the shadow, so nothing dark is refracted inward. It works the same on lite glass, which also reads what is behind it through its blur and magnification.
LiquidGlassShadow(
blur: 4,
opacity: 0.25,
insideGlass: false,
)On desktop#
A blurred path is rasterised on the pixel grid, so a moving ring steps a whole pixel at a time. At a phone's pixel ratio that never shows; at a desktop's 1 a sliding pill — the tab bar's, the slider's, the switch's — visibly jerks. On Windows, Linux and macOS the ring is therefore drawn from two blurred rounded rectangles, which are blurred at their exact sub-pixel position, so the shadow glides with the glass. It looks the same; mobile and the web keep the path.
Comments
Comments are GitHub Discussions — reply from either place.