What this is
liquid-glass is a small Compose Multiplatform library that gives you iOS 26-style frosted backdrop blur. It ships a Modifier.liquidGlass() plus three composables: GlassCard, GlassButton, and GlassNavBar. Same code runs on Android, iOS, Desktop, and Web.
Why I built it
Compose's built-in Modifier.blur blurs a composable's own content, not the backdrop behind it. Chris Banes's haze library solves the backdrop-blur problem cleanly and I'd happily recommend it. The remaining gap, for me, was graceful degradation. The iOS 26 "liquid glass" effect is heavy enough that Apple itself disables it on older hardware. On Android the same effect can chew through GPU memory on a 2GB device. I wanted a single composable I could drop in without writing per-device branching every time.
How it works
Three explicit quality tiers, auto-picked by platform:
| Tier | Blur radius | Saturation | Backdrop layer | Auto-picked on |
|---|---|---|---|---|
| Full | 24.dp | 1.4x | Full-res | Android 12+ (non-low-RAM), iOS 17+, Desktop, Web |
| Medium | 16.dp | 1.2x | 0.5x downsampled | iOS 15 to 16 (opt-in elsewhere) |
| Fallback | 0.dp | 1.0x | None, zero alloc | Android < 12 or isLowRamDevice, iOS < 15 |
The Fallback tier is the part I care about most. It allocates zero offscreen buffers and skips the blur entirely. The same code that draws frosted glass on a Pixel 9 quietly draws a flat tint with an edge sheen on a 2GB Android 11 device, without an OOM.
The composables consume the auto-detected tier through a LiquidGlassState:
@Composable
fun Screen() {
val state = rememberLiquidGlassState() // auto-picks per device
Box(Modifier.fillMaxSize()) {
// 1) Anything inside this box becomes the backdrop the glass samples from.
Image(
painter = painterResource(R.drawable.scenery),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize().liquidGlassSource(state),
)
// 2) A floating glass card on top, sampling the backdrop above.
GlassCard(
state = state,
modifier = Modifier.align(Alignment.Center).padding(24.dp),
) {
Text("Frosted, light-refracting surface, drop-in")
}
}
}
You can force a specific tier (for a brand-mandated "Full everywhere" look) or downgrade for low-end shells:
val state = rememberLiquidGlassState(LiquidGlassQuality.Full)
val state = rememberLiquidGlassState(LiquidGlassQuality.Fallback)
What it isn't
It's 0.1.0. There's no GlassDialog or GlassBottomSheet Material 3 wrapper yet, no dynamic-color edge sheen sampled from the captured backdrop, and no Sk SL refraction shader. Those are on the roadmap. If you need any of those today, haze is more mature and very flexible.
Try it
// gradle/libs.versions.toml
[libraries]
liquid-glass = { module = "io.github.nadeemiqbal:liquid-glass", version = "0.1.0" }
// commonMain dependencies
kotlin {
sourceSets {
commonMain.dependencies {
implementation(libs.liquid.glass)
}
}
}
Links
Repo: https://github.com/NadeemIqbal/liquid-glass
Maven Central: https://central.sonatype.com/artifact/io.github.nadeemiqbal/liquid-glass

Top comments (0)